Resizing and Cropping Images with Canvas

Learn how to resize and crop images using JavaScript and the HTML5 Canvas element using controls, commonly seen in photo editing applications.

ImageResizingCroppingCanvas

In this tutorial we’re going to learn how to resize and crop an image using the HTML5 <canvas> element, and while we’re at it, let’s create some fancy controls for resizing, commonly seen in photo editing applications.

In a real world example a website or app might use a technique like this to resize and frame a profile picture before uploading. Whilst we could do this on the server, it would require the transfer of a potentially large file, which is slow. Instead we can resize the image on the client side before uploading it, which is fast.

We do this by creating an HTML5 <canvas> element and drawing the image to the canvas at a particular size, then extracting the new image data from the canvas as a data URI. Most browsers have good support for these methods, so you can probably use this technique right now, however just be aware of some limitations unrelated to browser support such as quality and performance.

Resizing very large images can cause the browser to slow down or in some cases, even crash. It makes sense to set reasonable limits on the file size just as you would when uploading a file. If quality is important you may find the resized image looks undesirable due to how the browser resampled it. There are some techniques to improve the quality of images downscaled with canvas, but they are not covered in this tutorial.

Take a look at the final result in this demo or download the ZIP file.

With that in mind, let’s get started!

The Markup

In our demo we’re going to start with an existing image:

<img class="resize-image" src="image.jpg" alt="Image" />

That’s it! That’s all the HTML we need for this demo.

The CSS

The CSS is also very minimal. First, define the styles for the resize-container and the image.

.resize-container {
    position: relative;
    display: inline-block;
    cursor: move;
    margin: 0 auto;
}

.resize-container img {
    display: block
}

.resize-container:hover img,
.resize-container:active img {
    outline: 2px dashed rgba(222,60,80,.9);
}

Next, define the position and style for each of the ‘resize handles’. These are the little squares at each corner of the image that we drag to resize.

.resize-handle-ne,
.resize-handle-ne,
.resize-handle-se,
.resize-handle-nw,
.resize-handle-sw {
    position: absolute;
    display: block;
    width: 10px;
    height: 10px;
    background: rgba(222,60,80,.9);
    z-index: 999;
}

.resize-handle-nw {
    top: -5px;
    left: -5px;
    cursor: nw-resize;
}

.resize-handle-sw {
    bottom: -5px;
    left: -5px;
    cursor: sw-resize;
}

.resize-handle-ne {
    top: -5px;
    right: -5px;
    cursor: ne-resize;
}

.resize-handle-se {
    bottom: -5px;
    right: -5px;
    cursor: se-resize;
}

The JavaScript

With the JavaScript start by defining some of the variables and initializing the Canvas and the target image.

var resizeableImage = function(image_target) {
    var $container,
    orig_src = new Image(),
    image_target = $(image_target).get(0),
    event_state = {},
    constrain = false,
    min_width = 60,
    min_height = 60,
    max_width = 800,
    max_height = 900,
    resize_canvas = document.createElement('canvas');
});

resizeableImage($('.resize-image'));

Next, we create the init function that will be called immediately. This function wraps the image with a container, creates resize handles and makes a copy of the original image used for resizing. We also assign the jQuery object for the container element to a variable so we can refer to it later and add a mousedown event listener to detect when someone begins dragging one of the handles.

var resizeableImage = function(image_target) {

// ...
    init = function(){

        // Create a new image with a copy of the original src
        // When resizing, we will always use this original copy as the base
        orig_src.src=image_target.src;

        // Add resize handles
        $(image_target).wrap('<div class="resize-container"></div>')
        .before('<span class="resize-handle resize-handle-nw"></span>')
        .before('<span class="resize-handle resize-handle-ne"></span>')
        .after('<span class="resize-handle resize-handle-se"></span>')
        .after('<span class="resize-handle resize-handle-sw"></span>');

        // Get a variable for the container
        $container =  $(image_target).parent('.resize-container');

        // Add events
        $container.on('mousedown', '.resize-handle', startResize);
    };

//...

    init();
}

The startResize and endResize functions do very little other than tell the browser to start paying attention to where the mouse is moving and when to stop paying attention.

startResize = function(e){
    e.preventDefault();
    e.stopPropagation();
    saveEventState(e);
    $(document).on('mousemove', resizing);
    $(document).on('mouseup', endResize);
};

endResize = function(e){
    e.preventDefault();
    $(document).off('mouseup touchend', endResize);
    $(document).off('mousemove touchmove', resizing);
};

Before we start tracking the mouse position we want to take a snapshot of the container dimensions and other key data points. We store these in a variable named event_state and use them later as a point of reference while resizing to work out the change in height and width.

saveEventState = function(e){
  // Save the initial event details and container state
  event_state.container_width = $container.width();
  event_state.container_height = $container.height();
  event_state.container_left = $container.offset().left; 
  event_state.container_top = $container.offset().top;
  event_state.mouse_x = (e.clientX || e.pageX || e.originalEvent.touches[0].clientX) + $(window).scrollLeft(); 
  event_state.mouse_y = (e.clientY || e.pageY || e.originalEvent.touches[0].clientY) + $(window).scrollTop();

  // This is a fix for mobile safari
  // For some reason it does not allow a direct copy of the touches property
  if(typeof e.originalEvent.touches !== 'undefined'){
	event_state.touches = [];
	$.each(e.originalEvent.touches, function(i, ob){
	  event_state.touches[i] = {};
	  event_state.touches[i].clientX = 0+ob.clientX;
	  event_state.touches[i].clientY = 0+ob.clientY;
	});
  }
  event_state.evnt = e;
}

The resizing function is where most of the action happens. This function is constantly invoked while the user is dragging one of the resize handles. Every time this function is called we work out the new width and height by taking the current position of the mouse relative to the initial position of the corner we are dragging.

resizing = function(e){ 
    var mouse={},width,height,left,top,offset=$container.offset();
    mouse.x = (e.clientX || e.pageX || e.originalEvent.touches[0].clientX) + $(window).scrollLeft(); 
    mouse.y = (e.clientY || e.pageY || e.originalEvent.touches[0].clientY) + $(window).scrollTop();

    width = mouse.x - event_state.container_left;
    height = mouse.y  - event_state.container_top;
    left = event_state.container_left;
    top = event_state.container_top;

    if(constrain || e.shiftKey){
        height = width / orig_src.width * orig_src.height;
    }

    if(width > min_width && height > min_height && width < max_width && height < max_height){
      resizeImage(width, height);  
      // Without this Firefox will not re-calculate the the image dimensions until drag end
      $container.offset({'left': left, 'top': top});        
    }
}

Next we add the option to constrain the image dimensions when toggled using the shift key or a variable.

Finally, we resize the image, but only if the new width and height are not outside the bounds of the min and max variables we initially set.

Note: Because we’re actually resizing the image and not just changing the height and width attributes, you might consider limiting how often resizeImage is called to improve performance. This is called debouncing or throttling.

Actually resizing the image

Drawing an image to the Canvas is as easy as drawImage. We set the height and width of the canvas first and always use the original copy of the full-sized image. We then use toDataURL on the Canvas to get a Base64-encoded version of the newly resized image and place this on the page.

There is a full explanation for all the parameters that can be used with the drawImage method in the cropping section of this tutorial.

resizeImage = function(width, height){
    resize_canvas.width = width;
    resize_canvas.height = height;
    resize_canvas.getContext('2d').drawImage(orig_src, 0, 0, width, height);   
    $(image_target).attr('src', resize_canvas.toDataURL("image/png"));  
};

Too simple? There is one small proviso: the image must be on the same domain as the page or on a server with cross-origin resource sharing (CORS) enabled. If it’s not, you might run into problems with an error about a ‘tainted canvas’.

Resizing from different corners

You should now have a working demo. But it’s not complete. At the moment, no matter which corner of the image we resize, it behaves as though we are resizing it from the bottom right. We want to be able to resize the image from any corner. To do this we need to understand how it should behave.

When resizing, the corner we’re dragging as well as its adjacent edges should move, while the corner directly opposite and its adjacent edges should remain fixed.

Shows which corner remains fixed when resizing an image

When we change the width and height of an image, the right and bottom edges move, while the top and left edges will stay the same. This means that by default, an image is resized from its bottom right corner.

We can’t change this default behavior, but when resizing from any corner other than the bottom right we can change the overall position of the image so that it appears as though the opposite corner and edges remain fixed. Let’s update our resizing function:

resizing = function(e){
  var mouse={},width,height,left,top,offset=$container.offset();
  mouse.x = (e.clientX || e.pageX || e.originalEvent.touches[0].clientX) + $(window).scrollLeft(); 
  mouse.y = (e.clientY || e.pageY || e.originalEvent.touches[0].clientY) + $(window).scrollTop();
  
  // Position image differently depending on the corner dragged and constraints
  if( $(event_state.evnt.target).hasClass('resize-handle-se') ){
    width = mouse.x - event_state.container_left;
    height = mouse.y  - event_state.container_top;
    left = event_state.container_left;
    top = event_state.container_top;
  } else if($(event_state.evnt.target).hasClass('resize-handle-sw') ){
    width = event_state.container_width - (mouse.x - event_state.container_left);
    height = mouse.y  - event_state.container_top;
    left = mouse.x;
    top = event_state.container_top;
  } else if($(event_state.evnt.target).hasClass('resize-handle-nw') ){
    width = event_state.container_width - (mouse.x - event_state.container_left);
    height = event_state.container_height - (mouse.y - event_state.container_top);
    left = mouse.x;
    top = mouse.y;
    if(constrain || e.shiftKey){
      top = mouse.y - ((width / orig_src.width * orig_src.height) - height);
    }
  } else if($(event_state.evnt.target).hasClass('resize-handle-ne') ){
    width = mouse.x - event_state.container_left;
    height = event_state.container_height - (mouse.y - event_state.container_top);
    left = event_state.container_left;
    top = mouse.y;
    if(constrain || e.shiftKey){
      top = mouse.y - ((width / orig_src.width * orig_src.height) - height);
    }
  }

  // Optionally maintain aspect ratio
  if(constrain || e.shiftKey){
    height = width / orig_src.width * orig_src.height;
  }

  if(width > min_width && height > min_height && width < max_width && height < max_height){
    // To improve performance you might limit how often resizeImage() is called
    resizeImage(width, height);  
    // Without this Firefox will not re-calculate the the image dimensions until drag end
    $container.offset({'left': left, 'top': top});
  }
}

We are now checking to see which resize-handle has been dragged and we’re moving the image while resizing it so that it appears as though the correct corner remains fixed.

Moving the image

Now that we can resize the image from any of its corners you might have noticed we can inadvertently change its position on the page. We need to give users the ability to move the image back into the center of frame. In the init function let’s add another event listener similar to the one we did earlier.

init = function(){

    //...

    $container.on('mousedown', 'img', startMoving);
}

We now add startMoving and endMoving functions similar to startResize and endResize.

startMoving = function(e){
    e.preventDefault();
    e.stopPropagation();
    saveEventState(e);
    $(document).on('mousemove', moving);
    $(document).on('mouseup', endMoving);
};

endMoving = function(e){
    e.preventDefault();
    $(document).off('mouseup', endMoving);
    $(document).off('mousemove', moving);
};

In the function moving we need to work out the new position of the top left edge of the container. This will be equal to the current position of the mouse, offset by the distance the mouse was from the top left corner when we started dragging the image.

moving = function(e){
    var  mouse={};
    e.preventDefault();
    e.stopPropagation();
    mouse.x = (e.clientX || e.pageX) + $(window).scrollLeft();
    mouse.y = (e.clientY || e.pageY) + $(window).scrollTop();
    $container.offset({
        'left': mouse.x - ( event_state.mouse_x - event_state.container_left ),
        'top': mouse.y - ( event_state.mouse_y - event_state.container_top ) 
    });
};

Cropping the image

Now that we can resize the image we might want to crop it as well. Rather than allowing users to crop the image to any size and shape, let’s create a frame that is the exact dimensions we require and ask users to position the image inside that frame. This gives them control over the zoom and framing, yet ensures the final image always the same size and shape.

To do this we need to add a the following HTML:

<div class="overlay">
    <div class="overlay-inner">
    </div>
</div>
<button class="btn-crop js-crop">Crop</button>

The styles for the overlay box are important, particularly it’s position, width and height as they are used to determine what part of the image is cropped. It’s also important to remember that the frame should always be visible on any background color. That is why I used a semi transparent white outline around the main box in my example.

.overlay {
    position: absolute;
    left: 50%;
    top: 50%;
    margin-left: -100px;
    margin-top: -100px;
    z-index: 999;
    width: 200px;
    height: 200px;
    border: solid 2px rgba(222,60,80,.9);
    box-sizing: content-box;
    pointer-events: none;
}

.overlay:after,
.overlay:before {
    content: '';
    position: absolute;
    display: block;
    width: 204px;
    height: 40px;
    border-left: dashed 2px rgba(222,60,80,.9);
    border-right: dashed 2px rgba(222,60,80,.9);
}

.overlay:before {
    top: 0;
    margin-left: -2px;
    margin-top: -40px;
}

.overlay:after {
    bottom: 0;
    margin-left: -2px;
    margin-bottom: -40px;
}

.overlay-inner:after,
.overlay-inner:before {
    content: '';
    position: absolute;
    display: block;
    width: 40px;
    height: 204px;
    border-top: dashed 2px rgba(222,60,80,.9);
    border-bottom: dashed 2px rgba(222,60,80,.9);
}

.overlay-inner:before {
    left: 0;
    margin-left: -40px;
    margin-top: -2px;
}

.overlay-inner:after {
    right: 0;
    margin-right: -40px;
    margin-top: -2px;
}

.btn-crop {
    position: absolute;
    vertical-align: bottom;
    right: 5px;
    bottom: 5px;
    padding: 6px 10px;
    z-index: 999;
    background-color: rgb(222,60,80);
    border: none;
    border-radius: 5px;
    color: #FFF;
}

Update the JavaScript with the following function and event listener:

init = function(){

    //...

    $('.js-crop').on('click', crop);
  
};

crop = function(){
    var crop_canvas,
        left = $('.overlay').offset().left - $container.offset().left,
        top =  $('.overlay').offset().top - $container.offset().top,
        width = $('.overlay').width(),
        height = $('.overlay').height();
        
    crop_canvas = document.createElement('canvas');
    crop_canvas.width = width;
    crop_canvas.height = height;
    
    crop_canvas.getContext('2d').drawImage(image_target, left, top, width, height, 0, 0, width, height);
    window.open(crop_canvas.toDataURL("image/png"));
}

The crop function is similar to the resizeImage function however instead of passing it height and width values we get the height and width from the overlay element.

For cropping, the canvas drawImage method requires nine parameters. The first parameter is the source image. The next four parameters indicate what part of the source image is used (the clipping box). The final four parameters indicate where on the canvas to start drawing the image and at what size.

Adding touch events and gesture detection

We’ve added mouse events, now let’s add support for touch enabled devices.

For mousedown and mouseup there are equivalent touch events, touchstart and touchend and for mousemove there is the equivalent touchmove. Someone obviously lacks a sense of humor because these events could have easily been named “touchdown” and “touchup”.

Let’s add touchstart and touchend everywhere we have a mousedown and mouseup event listener and touchmove everywhere we have mousemove.

// In init()...
$container.on('mousedown touchstart', '.resize-handle', startResize);
$container.on('mousedown touchstart', 'img', startMoving);

//In startResize() ...
$(document).on('mousemove touchmove', moving);
$(document).on('mouseup touchend', endMoving);

//In endResize()...
$(document).off('mouseup touchend', endMoving);
$(document).off('mousemove touchmove', moving);

//In  startMoving()...
$(document).on('mousemove touchmove', moving);
$(document).on('mouseup touchend', endMoving);

//In endMoving()...
$(document).off('mouseup touchend', endMoving);
$(document).off('mousemove touchmove', moving);

Since we’re resizing an image it might be reasonable to expect that some users will try common gestures like pinch zoom. There is a library called Hammer that provides a lot of convenience when working with gestures. But since we only need pinch zoom, in our case, it might be a more like a sledge hammer. Let me show you how easy it is to detect pinch zoom without any library.

You might have notice that in the saveEventState function we already stored the initial touch data; this will come in handy now.

First we check if the event contains two “touches” and measure the distance between them. We note this as the initial distance and then constantly measure how much this distance changes while moving. Let’s update the moving function:

moving = function(e){
  var  mouse={}, touches;
  e.preventDefault();
  e.stopPropagation();
  
  touches = e.originalEvent.touches;
  mouse.x = (e.clientX || e.pageX || touches[0].clientX) + $(window).scrollLeft(); 
  mouse.y = (e.clientY || e.pageY || touches[0].clientY) + $(window).scrollTop();
  $container.offset({
    'left': mouse.x - ( event_state.mouse_x - event_state.container_left ),
    'top': mouse.y - ( event_state.mouse_y - event_state.container_top ) 
  });
  // Watch for pinch zoom gesture while moving
  if(event_state.touches && event_state.touches.length > 1 && touches.length > 1){
    var width = event_state.container_width, height = event_state.container_height;
    var a = event_state.touches[0].clientX - event_state.touches[1].clientX;
    a = a * a; 
    var b = event_state.touches[0].clientY - event_state.touches[1].clientY;
    b = b * b; 
    var dist1 = Math.sqrt( a + b );
    
    a = e.originalEvent.touches[0].clientX - touches[1].clientX;
    a = a * a; 
    b = e.originalEvent.touches[0].clientY - touches[1].clientY;
    b = b * b; 
    var dist2 = Math.sqrt( a + b );

    var ratio = dist2 /dist1;

    width = width * ratio;
    height = height * ratio;
    // To improve performance you might limit how often resizeImage() is called
    resizeImage(width, height);
  }
};

We divide the current distance by initial distance to get the ratio and how much to scale the image. We work out the new width and height and then resize the image.

ImageResizingCroppingCanvas01

And that’s it. Take a look at the demo or download the ZIP file.

In my testing, Chrome prevented the default browser response for pinch zoom, which is to change the page zoom, but Firefox didn’t.

I hope you found this tutorial useful. I suggest further reading on drag and drop and file upload techniques and look forward to see how people might combine these techniques to create some beautiful user interfaces.

Previous:
Next:

Tagged with:

Mike is web developer living in Merimbula on the south east coast of Australia. He loves the web and sometimes writes about it. He is honored that you are reading his bio.

View all contributions by

Website: http://madebymike.com.au

Related Articles

CSS Reference

Learn about all important CSS properties from the basics with our extensive and easy-to-read CSS Reference.

It doesn't matter if you are a beginner or intermediate, start learning CSS now.

Feedback 108

  1. 1

    Hello, I have a wordpress website and want to implement this. Can you confirm how i would go about it ?

  2. 3

    Great Tutorial!Its working perfectly for small images but i am not able to crop large images(around 900 kb).I am however able to pan them.Can you please guide me what is causing the issue and what i need to change ?

    • 4

      hi,
      i have the same issue , i can’t resizing with big picture…

      i has try : img {max width:400px} and now i can resizing .. :)

      ….but now when i try to save, he save with the size of big picture so the result is not the same of the display .. any idea ? ( sorry for my english )

    • 5

      In the crop function, you should obtain a ratio of the original image width and its screen width. I assigned an id to the image in order to do this easily. Then apply the ratio to the left, top, width and height of the overlay variable. That should do it…looks like this:

      var myimg = document.getElementById(‘myimg’);
      var ratio = myimg.naturalWidth / myimg.width;
      var crop_canvas,
      left = ($(‘.overlay’).offset().left – $container.offset().left)*ratio,
      top = ($(‘.overlay’).offset().top – $container.offset().top)*ratio,
      width = ($(‘.overlay’).width())*ratio,
      height = ($(‘.overlay’).height())*ratio;

      I also needed a 16/9 crop, so I set the overlay’s width and height to 320/180. The :before and :after got fugly after that so I made an oldschool table and put the overlay in the center of it, three tr, and three td per row with left and right td of each row with the dashed border, so it looks decent. I used Jquery draggable for the table and Jquery resizable for the overlay with aspectRatio true so the 16/9 remains on resize. I then did this so all my pictures have the exact same dimension regardless of the original size…

      crop_canvas = document.createElement(‘canvas’);
      crop_canvas.width = 640;
      crop_canvas.height = 360;

      crop_canvas.getContext(‘2d’).drawImage(image_target, left, top, width, height, 0, 0, 640, 360);

      You can use regular CSS to size your image so long as it maintains its original aspect ratio, 4:3 or whatever. Thanks for the tutorial. I was attempting to do this with my own but I only had a resizable/draggable overlay, functional, but not pretty. Being able to resize and move the image is excellent. If you allow the image to be skewed, then you’ll need a separate ratio for left/width and for top/height

  3. 9

    Hi!
    Thanks for the great tutorial.

    I need to know how can hide the dotted line box and freeze the image once I done resizing and everything.

  4. 11

    Wow, this is plain amazing.

    Rather than display the cropped image though, I would like to save it. Another user posted some code but I don’t quite understand how he transitions the data from JavaScript into PHP. What method would YOU use to save the image rather than display it?

  5. 12

    Okay, so with saving the image is actually a pretty simple process, as outlined here: http://permadi.com/2010/10/html5-saving-canvas-image-data-using-php-and-ajax/

    First, you need to make a change in the component.js file, replacing the window.open() function with the code listed here to send the data to a php receiving file. In my case, I created a file called “savefile.php” and here is the code changes to the component.js file:

    *******************************************************************************
    crop = function(){
    //Find the part of the image that is inside the crop box
    var crop_canvas,
    left = $(‘.overlay’).offset().left – $container.offset().left,
    top = $(‘.overlay’).offset().top – $container.offset().top,
    width = $(‘.overlay’).width(),
    height = $(‘.overlay’).height();

    crop_canvas = document.createElement(‘canvas’);
    crop_canvas.width = width;
    crop_canvas.height = height;

    crop_canvas.getContext(‘2d’).drawImage(image_target, left, top, width, height, 0, 0, width, height);

    // The default operation will simply open a new tab showing the cropped image
    // window.open(crop_canvas.toDataURL(“image/png”));

    // The following code is taken from http://permadi.com/2010/10/html5-saving-canvas-image-data-using-php-and-ajax/
    // It shows how to post the image data as a POST variable into a url that points to a php file that receives the data…
    var canvasData = crop_canvas.toDataURL(“image/png”);
    var ajax = new XMLHttpRequest();
    ajax.open(“POST”,’savefile.php’,false);
    ajax.setRequestHeader(‘Content-Type’, ‘application/upload’);
    ajax.send(canvasData )
    }

    init();
    };
    *******************************************************************

    Then create the savefile.php file:
    ****************************************************************************************

    *****************************************************************************

    And that’s all there is to it. Hope this helps folks out there!

    • 13

      the code for the php didn’t show. here it is:

      // The file should be saved using the interpreter’s ID number.
      session_start();
      $imgFile = “http://www.ubpcorp.com/members/images/” . $_SESSION[‘agent’] . “.jpg”;

      if (isset($GLOBALS[“HTTP_RAW_POST_DATA”])) {
      // Get the data
      $imageData=$GLOBALS[‘HTTP_RAW_POST_DATA’];

      // Remove the headers (data:,) part.
      // A real application should use them according to needs such as to check image type
      $filteredData=substr($imageData, strpos($imageData, “,”)+1);

      // Need to decode before saving since the data we received is already base64 encoded
      $unencodedData=base64_decode($filteredData);

      //echo “unencodedData”.$unencodedData;

      // Save file.
      $fp = fopen( $imgFile, ‘wb’ );
      fwrite( $fp, $unencodedData);
      fclose( $fp );
      }

      header (‘Location: index.php’);

    • 14

      Victor – You solution is exactly what I need to do! I have been trying and trying to get your code to work. I appended the lines to crop = function in component.js (see below).
      I’ve read up on the savefile.php, read the original article you sourced and tried a few options found on there but to no luck. You would think saving a crop image wouldnt be so hard!

      Was there anything else you did in the code to get it to work? Your help greatly appreciated!

      crop = function(){
      //Find the part of the image that is inside the crop box
      var crop_canvas,
      left = $(‘.overlay’).offset().left – $container.offset().left,
      top = $(‘.overlay’).offset().top – $container.offset().top,
      width = $(‘.overlay’).width(),
      height = $(‘.overlay’).height();

      crop_canvas = document.createElement(‘canvas’);
      crop_canvas.width = width;
      crop_canvas.height = height;
      crop_canvas.getContext(‘2d’).drawImage(image_target, left, top, width, height, 0, 0, width, height);

      //=== set our canvas data
      var canvasData = crop_canvas.toDataURL(‘image/png’);

      //=== call ajax to fire php save function
      var ajax = new XMLHttpRequest();
      ajax.open(‘POST’,’savefile.php’,false);
      ajax.setRequestHeader(‘Content-Type’, ‘application/upload’);
      ajax.send(canvasData);
      }

  6. 15

    Hi,

    thanks for this, it’s very helpfull.
    But I have a problem. My website have to work on mobile devices. I changed the overlay size to crop a 390px * 390px picture. It works fine, but on smartphones, the screen’s size is 320px (well, it’s the size of my website on smartphone).

    How can I change on mobile the size of all (the picture, the crop zone, etc…) but get after crop my 390px * 390px picture ?

  7. 19

    Hi, Mike.
    This is awesome article, I added some more features base on your example code and upload it to github.com. Please feel free to comment it.

    Thank you.
    Wut

  8. 23

    Hi,
    This is amazing! Thanks a lot!

    But I have a problem with multiple image support.
    What should I do with component.js file that makes multiple image supporting.

    • 25

      Hi, I also have this issue, does anybody know how to do it with multiple images? What does “make each images has component.js” mean, I don’t understand how to do this.
      Thanks a lot

  9. 27

    Hey there Mike,

    Really great article! I’ve been trying to implement it across multiple images by simply calling resizeableImage() multiple times (once for each image, targeting each image individually). For example:

    resizeableImage($(‘.resize-image1’));
    resizeableImage($(‘.resize-image2’));

    However, doing this causes the drag handles on the first image to actually resize the second image. And when you try and move the first image, the second image moves instead. I’ve uploaded it to http://imageresize.mindwire.com.au so you can see what I mean.
    I’ve removed any extraneous html code so that I can focus on the issue at hand… otherwise, the code is the same as your original code (other than the second call to resizeableImage for the second image).

    Any help would truly be appreciated.

    Damian – Cairns, QLD, Australia

    • 28

      Have tried many things to tackle the issue… for example, putting ids on the canvases and trying to target them explicitly whilst in resizing().
      I think the issue starts occurring at the the binding of resizing() within startResize(), as follows:

      $(document).on(‘mousemove touchmove’, resizing); //Problem starts here!

      After applying id’s to the canvases and then logging the canvas id’s to the console, looks like the last canvas created always gets resized/moved regardless.
      Have spent the last 4 nights working on it to no avail… totally hit a brick wall. :(

      Would really appreciate any guidance on how to solve it.
      Cheers
      Damian

  10. 29

    Hi Guys,

    Thanks for the tutorial, i was stared using this recently and having some issue, when i was trying to adjust canvas height,width dynamically.

    Any help will be appreciated,

    Thanks

  11. 30

    Hello, I was looking at the code and made some implementations, well here we go:
    First I took the picture, leaving the ‘src’ empty.
    According added a field ‘input’ for image and so the person puts image runs the ‘FileReader’ of html5, so I can put the image of the person to ‘crop’
    So far was a success.
    The problem is when I use ‘FileReader’ and use to display the image by ‘src’, I can not do the resizing of the image.
    Can someone help me?

Follow this discussion

Leave a Comment