📜 ⬆️ ⬇️

Adding an avatar, cropping a photo on a mobile device and a desktop on JavaScript and PHP

Good day! In developing the site, I approached the fact that I need to add the function of adding an avatar to users on the desktop and mobile devices. I searched for materials for a long time, even at first decided to add a library with ready-made functions already written by someone (I don’t remember how the article was called, but it definitely was on Habré and some libraries were reviewed there). After testing these connected libraries, I decided to write everything in JavaScript and PHP (except for using ajax to work with php) using HTML5. For demonstration I created a page for habr: demo for habrahabr .

Let's start with the general part. Markup.

It's simple. Inside the main unit (in my case 400x400px) I created a block with an image, an absolute block for calculating the trimming coordinates (200x200px) and an absolute block for the entire width of the working area, which I called the touchpad (400x400px). Immediately I draw your attention to the fact that the sizes of these blocks are purely individual.

Functions for the desktop.
')
It all starts with the onmousedown function. The first thing I added to this is the zoom by pressing the left mouse button while holding the shift key. We work with the touchpad. To transfer the php coordinates to the handler, I created 4 input type = “hidden” with id values ​​like x1 - coordinate of the image offset offset along the x axis, y1 - respectively along the y axis, w - source image width, h - source image height.

//   var image = document.getElementById('image'); //  var a = document.getElementById('touch_pad'); // input-    var x1 = document.getElementById('x1'); var y1 = document.getElementById('y1'); var w = document.getElementById('w'); var h = document.getElementById('h'); //      a.onmousedown = function(e){ //  shift,       if(e.shiftKey){ //    var koefx = e.clientX + e.clientY; //   var d = image.offsetWidth; //      a.onmousemove = function(e){ //    ,     koefx var reli = e.clientX + e.clientY; //        image.style.width = d + reli*2 - koefx*2 + 'px'; var wid = image.width; var heig = image.height; //     400px,    200px      - //    100px  x  y var ll = 100 - image.offsetLeft; var tt = 100 - image.offsetTop; //      x  y        x1.setAttribute('value', ll); y1.setAttribute('value', tt); w.setAttribute('value', wid); h.setAttribute('value', heig); } } 

As you can see here everything is simple, a little later we will declare a function for zooming by scrolling the mouse wheel, which will give additional functionality to the user.

Next we start the function of changing the position of the original image, if shift is not clamped:

 else { //    var x = e.pageX; var y = e.pageY; //    var lleft = image.offsetLeft; var ttop = image.offsetTop; //     x  y var lleft = x - lleft; var ttop = y - ttop; //      a.onmousemove = function(e){ //    x = e.pageX; y = e.pageY; //     var l = image.offsetLeft; var t = image.offsetTop; //         var ll = 100 - Number(l); var tt = 100 - Number(t); //          image.style.marginLeft = x - lleft; image.style.marginTop = y - ttop; var wid = image.width; var heig = image.height; x1.setAttribute('value', ll); y1.setAttribute('value', tt); w.setAttribute('value', wid); h.setAttribute('value', heig); } } //   mouseup   mousemove a.onmouseup = function(){ a.onmousemove = function(){} } return } 

As you can see here everything is very simple as regards getting the coordinates of the cropping and changing the scale.
Next you need to do everything the same, but with the touchstart and touchmove methods for mobile devices:

 a.ontouchstart = function(e){ //        //    ,      scal(),    if(e.targetTouches.length == 2){ scal(e); } //  ,      if(e.targetTouches.length == 1){ //     targetTouches  ,      //   ,  [0],        (  ) //  e (  mousedown  mousemowe     ) // e   targetTouches   [0]     //  handl var handl = e.targetTouches[0]; var x = handl.pageX; var y = handl.pageY; var lleft = image.offsetLeft; var ttop = image.offsetTop; var lleft = x - lleft; var ttop = y - ttop; a.ontouchmove = function(e) { var handle = e.targetTouches[0] x = handle.pageX; y = handle.pageY; var l = image.offsetLeft; var t = image.offsetTop; var ll = 100 - Number(l); var tt = 100 - Number(t); image.style.marginLeft = x - lleft; image.style.marginTop = y - ttop; a.ontouchend = function(){ var wid = image.width; var heig = image.height; x1.setAttribute('value', ll); y1.setAttribute('value', tt); w.setAttribute('value', wid); h.setAttribute('value', heig); } } } return } 

That is, in principle, the functions are the same, except that when working with the sensor, we can use more than one “cursor”.

Then a little harder. If the touch is still 2, then you need to set the zoom function, and there are some pitfalls. Firstly, when zooming in / out, you need to make it so that the image scale does not change from the upper left corner, but from the center. Secondly, the coefficient must always be a positive number and take the value “zero” when the calculation function is triggered. And so it went:

 //     - function scal(e){ //   touc    var touc = e.targetTouches; var cur_w = image.offsetWidth; //     var koef = Math.sqrt(Math.pow((touc[0].clientX - touc[1].clientX), 2) + Math.pow((touc[0].clientY - touc[1].clientY), 2)); //    touchmove      a.ontouchmove = function(e){ var tou = e.targetTouches; var relis = Math.sqrt(Math.pow((tou[0].clientX - tou[1].clientX), 2) + Math.pow((tou[0].clientY - tou[1].clientY), 2)); var im = image.offsetWidth; //     image.style.width = cur_w + relis*2 - koef*2 + 'px'; } //   touchend   a.ontouchend = function(e){ var wid = image.width; var heig = image.height; var ll = 100 - image.offsetLeft; var tt = 100 - image.offsetTop; x1.setAttribute('value', ll); y1.setAttribute('value', tt); w.setAttribute('value', wid); h.setAttribute('value', heig); } } 

It remains to add changes in the scale when scrolling the mouse wheel on the desktop:

 //    a.onwheel = function(e){ var t = e.deltaY/5; var d = image.offsetWidth; image.style.width = dt; var wid = image.width; var heig = image.height; var ll = 100 - image.offsetLeft; var tt = 100 - image.offsetTop; x1.setAttribute('value', ll); y1.setAttribute('value', tt); w.setAttribute('value', wid); h.setAttribute('value', heig); return } 


Each person chooses the image handler himself, I personally use the following script:

 <? if(isset($_POST['crop'])){ $filename = 'img.jpg'; $new_filen = 'ava/img.jpg'; list($current_width, $current_height) = getimagesize($filename); $x1 = $_POST['x']; $y1 = $_POST['y']; $w = $_POST['w']; $h = $_POST['h']; $new = imagecreatetruecolor($w, $h); $current_image = imagecreatefromjpeg($filename); imagecopyresampled($new, $current_image, 0, 0, 0, 0, $w, $h, $current_width, $current_height); $final = imagecreatetruecolor(200, 200); imagecopy($final, $new, 0, 0, $x1, $y1, 200, 200); $fin_creat = imagejpeg($final, $new_filen, 100); $handle = fopen($new_filen, "r"); unlink($filename ); } ?> 

Thanks for attention!

Source: https://habr.com/ru/post/314180/


All Articles