Search code examples
javascriptjcrop

Is there a way to use JCrop to crop an area larger than the actual image?


From what I can tell, JCrop will not let me set things up so the user can crop outside the actual image and include surrounding whitespace. Is there a way to do that?

To help explain what I mean, say we are restricting our crop to a 16:9 ratio. That works fine for an image with a naturally wide subject:

enter image description here

But sometimes the source image that a user wants to use does not comfortably accommodate the desired ratio:

enter image description here

Instead, we'd like to allow them to include space outside the image by making the crop area larger than the image itself:

enter image description here

I've been messing around with JCrop and looking through the manual and Google for a while and it doesn't look like this is possible (without modifying JCrop). Am I wrong? If so, how do you do it?

FWIW, the actual images in this case will be product/organization logo images, which come in a large variety of aspect ratios, and almost always the images available to people have almost no whitespace around the text/imagery. Which means any fixed aspect ratio crop restricted to the bounds of the image will almost certainly chop off either the top+bottom or left+right sides of the image.


Solution

  • My solution was to create a temporary canvas with square dimensions equal to the largest side of the image. I made the canvas background white and added the image in the center. Then I created a new image and used the canvas as the image source. Then I used that image with jcrop. It's slower, but it works!

    Here's an example:

    img.onload = function(){ 
        // get the largest side of the image
        // and set the x and y coordinates for where the image will go in the canvas
        if( img.width > img.height ){
            var largestDim = img.width;
            var x = 0;
            var y = (img.width-img.height)/2;
        }
        else{
            var largestDim = img.height;
            var y = 0;
            var x = (img.height-img.width)/2;
        }
        // create a temporary canvas element and set its height and width to largestDim
        canvastemp = document.createElement("canvas");
        canvastemp.width = canvastemp.height = largestDim;
        var ctx = canvastemp.getContext('2d');
        // set the canvas background to white
        ctx.fillStyle="#FFFFFF";
        ctx.fillRect(0, 0, canvastemp.width, canvastemp.height);
        // center the image in the canvas
        ctx.drawImage(img, x, y, img.width, img.height);
        // create a new image and use the canvas as its source
        var squaredImg = document.createElement("img");
        squaredImg.src = canvastemp.toDataURL();
        // add jcrop once the image loads
        squaredImg.onload = function(){
            addJcrop(squaredImg);   
        }
    };
    
    function addJcrop(img){
       // your jcrop code
    }
    

    This way users can choose to include the entire image in the crop if they wish.