fengyuanchen Cropper - How to Fit Image into Canvas If Rotated?

12.1k views Asked by At

I gone through documentation of cropper by fengyuanchen. I want the image to be fit by default into canvas if rotated. But I couldnt find a way to achieve this. Any idea how to achieve this functionality?

I want it to be like this to be default: link

Check issue demo here: link

5

There are 5 answers

0
oomer On
var photoToEdit = $('.photo_container img');
$( photoToEdit ).cropper({
   autoCrop : true,
   crop: function(e) {}
});
$("#rotate_left_btn").click( function () {
   $( photoToEdit ).cropper('rotate', -90);
   var containerHeightFactor = $(".photo_container").height() / $( photoToEdit).cropper('getCanvasData').height;
   if ( containerHeightFactor < 1 ) { // if canvas height is greater than the photo container height, then scale (on both x and y
      // axes to maintain aspect ratio) to make canvas height fit container height
      $( photoToEdit).cropper('scale', containerHeightFactor, containerHeightFactor);
   } else if ( $( photoToEdit).cropper('getData').scaleX != 1 || $( photoToEdit).cropper('getData').scaleY != 1 ) { // if canvas height
      // is NOT greater than container height but image is already scaled, then revert the scaling cuz the current rotation will bring
      // the image back to its original orientation (landscape/portrait)
      $( photoToEdit).cropper('scale', 1, 1);
   }
}
0
Afonso Gomes On

Not a direct answer to the question ... but i'm betting many people that use this plugin will find this helpfull..

Made this after picking up @AlexanderZ code to rotate the image.

So ... If you guys want to ROTATE or FLIP a image that has already a crop box defined and if you want that cropbox to rotate or flip with the image ... use these functions:

function flipImage(r, data) {

    var old_cbox = $image.cropper('getCropBoxData');
    var new_cbox = $image.cropper('getCropBoxData');
    var canv     = $image.cropper('getCanvasData');

    if (data.method == "scaleX") {
        if (old_cbox.left == canv.left) {
            new_cbox.left = canv.left + canv.width - old_cbox.width;
        } else {
            new_cbox.left = 2 * canv.left + canv.width - old_cbox.left - old_cbox.width;
        }

    } else {
        new_cbox.top = canv.height - old_cbox.top - old_cbox.height;
    }

    $image.cropper('setCropBoxData', new_cbox);

    /* BUG: When rotated to a perpendicular position of the original position , the user perceived axis are now inverted. 
    Try it yourself: GO to the demo page, rotate 90 degrees then try to flip X axis, you'll notice the image flippped vertically ... but still ... it fliped in relation to its original axis*/

    if ( r == 90 || r == 270 || r == -90 || r == -270 ) {

        if ( data.method == "scaleX") {

            $image.cropper("scaleY", data.option);

        } else {

            $image.cropper("scaleX", data.option);

        }

    } else {

        $image.cropper(data.method, data.option);

    }

    $image.cropper(data.method, data.option);

}





function rotateImage(rotate) {

    /* var img = $image.cropper('getImageData'); */

    var old_cbox = $image.cropper('getCropBoxData');
    var new_cbox = $image.cropper('getCropBoxData');
    var old_canv = $image.cropper('getCanvasData');
    var old_cont = $image.cropper('getContainerData');

    $image.cropper('rotate', rotate);

    var new_canv = $image.cropper('getCanvasData');

    //calculate new height and width based on the container dimensions
    var heightOld = new_canv.height;
    var widthOld = new_canv.width;
    var heightNew = old_cont.height;
    var racio = heightNew / heightOld;
    var widthNew = new_canv.width * racio;
    new_canv.height = Math.round(heightNew);
    new_canv.width = Math.round(widthNew);
    new_canv.top = 0;

    if (new_canv.width >= old_cont.width) {
        new_canv.left = 0;
    } else {
        new_canv.left = Math.round((old_cont.width - new_canv.width) / 2);
    }

    $image.cropper('setCanvasData', new_canv);

    if (rotate == 90) {
        new_cbox.height  = racio * old_cbox.width;
        new_cbox.width   = racio * old_cbox.height;

        new_cbox.top     = new_canv.top + racio * (old_cbox.left - old_canv.left);
        new_cbox.left    = new_canv.left + racio * (old_canv.height - old_cbox.height - old_cbox.top);
    }

    new_cbox.width  = Math.round(new_cbox.width);
    new_cbox.height = Math.round(new_cbox.height);
    new_cbox.top    = Math.round(new_cbox.top);
    new_cbox.left   = Math.round(new_cbox.left);

    $image.cropper('setCropBoxData', new_cbox);

}
3
plugowski On

This is my extended code provided by AlexanderZ to avoid cuttong wider images than container :)

var contData = $image.cropper('getContainerData');

$image.cropper('setCropBoxData',{
    width: 2, height: 2, top: (contData.height/ 2) - 1, left: (contData.width / 2) - 1
});

$image.cropper('rotate', 90);

var canvData = $image.cropper('getCanvasData');
var newWidth = canvData.width * (contData.height / canvData.height);

if (newWidth >= contData.width) {
    var newHeight = canvData.height * (contData.width / canvData.width);
    var newCanvData = {
        height: newHeight,
        width: contData.width,
        top: (contData.height - newHeight) / 2,
        left: 0
    };
} else {
    var newCanvData = {
        height: contData.height,
        width: newWidth,
        top: 0,
        left: (contData.width - newWidth) / 2
    };
}

$image.cropper('setCanvasData', newCanvData);
$image.cropper('setCropBoxData', newCanvData);
4
EscapeNetscape On

I fixed this behavior but for my special needs. I just needed one rotate button which rotates an image in 90° steps. For other purposes you might extend/change my fix. It works in "strict" mode by dynamically change the cropbox dimensions.

Here my function which is called, when I want to rotate an image. Ah and additionally the misplacement bug has also been fixed.

var $image;

function initCropper() {
$image = $('.imageUploadPreviewWrap > img').cropper({
  autoCrop : true,
  strict: true,
  background: true,
  autoCropArea: 1,
  crop: function(e) {
  }
});
}

function rotateImage() {    
    //get data
    var data = $image.cropper('getCropBoxData');
    var contData = $image.cropper('getContainerData');
    var imageData = $image.cropper('getImageData');
    //set data of cropbox to avoid unwanted behavior due to strict mode
    data.width = 2;
    data.height = 2;
    data.top = 0;
    var leftNew = (contData.width / 2) - 1;
    data.left = leftNew;
    $image.cropper('setCropBoxData',data);
    //rotate
    $image.cropper('rotate', 90);
    //get canvas data
    var canvData = $image.cropper('getCanvasData');
    //calculate new height and width based on the container dimensions
    var heightOld = canvData.height;
    var heightNew = contData.height;
    var koef = heightNew / heightOld;
    var widthNew = canvData.width * koef;
    canvData.height = heightNew;
    canvData.width = widthNew;
    canvData.top = 0;
    if (canvData.width >= contData.width) {
      canvData.left = 0;
    }
    else {
      canvData.left = (contData.width - canvData.width) / 2;
    }
    $image.cropper('setCanvasData', canvData);
    //and now set cropper "back" to full crop
    data.left = 0;
    data.top = 0;
    data.width = canvData.width;
    data.height = canvData.height;
    $image.cropper('setCropBoxData',data);
  } 
0
SirajShaikh On

I Fixed this issue hope fully. i have added or changed the option to 0 (viewMode: 0,). Now its working well.

cropper = new Cropper(image, {
            dragMode: 'none',
            viewMode: 0,
            width: 400,
            height: 500,
            zoomable: true,
            rotatable: true,
            crop: function(e) {
            }
        });

document.getElementById('rotateImg').addEventListener('click', function () {
        cropper.rotate(90);
    });