Make Jcrop tracker not rotate when cropping a rotated image
Asked Answered
S

5

8

I'm trying to crop an image using Jcrop, but when I use jqueryrotate on the image, something weird happens.

I rotate the image 90 degress then I activate the JCrop, the JCrop does not follow the image rotated, so I also rotate the Jcrop-holder. The resulting image is ok, but when I select a section to crop, I have noticed that my tracker is also rotated. When I drag it up, it goes right, when I drag it left, it goes down.

What happens enter image description here

Then it goes enter image description here How do I make the crop selection tool stay upright?

My html:

    <div class="img-canvas" style="background-color:#cccccc;" >
            <img id="image_canv" src="<?php echo $imagesource;?>"> 
        </div> 

My Jquery:

$('#rotatephoto').click(function () {
value += 90;

JcropAPI = $('#image_canv').data('Jcrop');
    if(JcropAPI != null)
    {
    JcropAPI.destroy();
    }

var h = $('.img-canvas').height();
var w = $('.img-canvas').width();
$('.img-canvas').css("position","fixed");
$('.img-canvas').css("width",w);

$('.img-canvas').css("height",h);

$('#image_canv').Jcrop({
    onSelect: showCoords2,
    onChange: showCoords2,
    setSelect:   [ 0, 100, 50, 50 ]
    });

JcropAPI = $('#image_canv').data('Jcrop');
JcropAPI.enable();

var h2 = $('.jcrop-holder').height();
var w2 = $('.jcrop-holder').width();

if(h2  < 630)
{
var tempp = (630 - h2)/2;
$('.jcrop-holder').css("margin-top",tempp);
}
if(w2  < 630)
{
var tempp = (630 - w2)/2;
$('.jcrop-holder').css("margin-left",tempp);
} 

$('.jcrop-holder').rotate(value);
$("#image_canv").rotate(value);
});
Searle answered 19/11, 2013 at 3:44 Comment(0)
S
5

Yes, the JCrop has the problem of selection direction error after rotated by JQuery rotate. I had to resolve it by change the JCrop's js code to support rotate.

Fortunatly, it's not hard to do, you can do it yourself by replace one line: 136 to sub codes:

    //========= begin replace origin line 136 for rotate
    var x = pos[0] - lloc[0];
    var y = pos[1] - lloc[1];
    var rotate = options.rotate || 0;
    var angle = (rotate / 90) % 4;
    if (angle == 1) {
      var temp = x;
      x = y;
      y = - temp;
    } else if (angle == 2) {
      x = -x;
      y = -y;
    } else if (angle == 3) {
      var temp = x;
      x = -y;
      y = temp;
    }
    Coords.moveOffset([x, y]);
    //========= end replace origin line 136 for rotate

or you can get the updated code by url: https://github.com/ergoli/Jcrop/tree/master/js

be careful! you should transfer the rotate option after each rotate click:

jCropApi.setoptions({rotate : 90});  //rotate 90

good luck!

Sanitarium answered 27/12, 2013 at 4:30 Comment(2)
Could you provide a JSFiddle? Something doesn't seem to work for me.Sym
setOptions in recent versions of jCropSchaller
C
1

I jumped off of ergoli, but instead of jquery rotate I used css classes like:

.rotate90{
    /* Safari */
  -webkit-transform: rotate(90deg);

  /* Firefox */
  -moz-transform: rotate(90deg);

  /* IE */
  -ms-transform: rotate(90deg);

  /* Opera */
  -o-transform: rotate(90deg);

  /* Internet Explorer */
  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);

}

Then I made similar classes for 180 and -90.

I found it was simpler for me to just alter the mouseAbs function

function mouseAbs(e) //{{{
    {
      switch (options.rotate) {
          case 90:
            return [(e.pageY - docOffset[1]), -(e.pageX - docOffset[0] - options.imgHeight)];
            break;
          case 270:
            return [(e.pageY - docOffset[1]), -(e.pageX - docOffset[0] - options.imgHeight)];
            break;
          case -90:
            return [-(e.pageY - docOffset[1] - options.imgWidth), (e.pageX - docOffset[0] )];
            break;
          case 270:
            return [-(e.pageY - docOffset[1] - options.imgWidth), (e.pageX - docOffset[0] )];
            break;
          case 180:
            return [-(e.pageX - docOffset[0]- options.imgWidth), -(e.pageY - docOffset[1] - options.imgHeight)];
            break;
          case -180:
            return [-(e.pageX - docOffset[0]- options.imgWidth), -(e.pageY - docOffset[1] - options.imgHeight)];
            break;
          default:
            return [(e.pageX - docOffset[0]), (e.pageY - docOffset[1])];
            break;
          }

    }

Just had to make sure my .jcrop-holder had the right rotate class at the right time and instanciate jcrop with the rotate and image dimensions.

this.image.Jcrop({
    rotate: that.angle,
    imgHeight: that.image.height(),
    imgWidth: that.image.width(),
    onSelect: function(c){
        that.x1 = c.x;
        that.x2 = c.x2;
        that.y1 = c.y;
        that.y2 = c.y2;
        that.w  = c.w;
        that.h  = c.h;
    }
});

This is not a particularly elegant solution, but its working currently.

Concordat answered 16/1, 2014 at 23:37 Comment(2)
Great!!! I did it and crop selection works fine after rotation but when I try to move the selection box, it moves in a different mouse direction. Also, it shows the wrong mouse pointer over the resize points (corners and middle). Any idea about how to fix this?Illgotten
check your implementation of the mouseAbs for mouse position. for the cursor i think this may be resolved by the first bit, otherwise css issue.Concordat
G
1

I recently tried implementing this too, but wasn't able to get the approaches mentioned in the other answers working the way I wanted. In particular, I was having trouble with resizing the crop when it was rotated. I looked into updating Jcrop to fix the issue, but decided an alternative would be easier.

I instead opted to rotate the images outside of Jcrop using the JavaScript Load Image library and then crop the rotated image. The loadImage method in there takes an orientation option that can be used to perform the rotation. Depending on what you're trying to do, you may need to transform the resulting crop afterwards, but I found that to be easier than messing with the internals of Jcrop.

Geochronology answered 19/8, 2014 at 21:7 Comment(0)
B
1

I used Dan's approach as a jumping off point but I don't have enough reputation to leave a comment on Dan Baker's answer so I'm submitting another answer. His mouseAbs function didn't work for me at all, I modified it as follows:

function mouseAbs(e) 
{
  switch (options.rotate) {
      case 90:
        return [(e.pageY - docOffset[1]), -(e.pageX - docOffset[0])];
      case 180:
        return [-(e.pageX - docOffset[0]), -(e.pageY - docOffset[1])];
      case 270:
        return [-(e.pageY - docOffset[1]), (e.pageX - docOffset[0])];
      default:
        return [(e.pageX - docOffset[0]), (e.pageY - docOffset[1])];
      }
}

Everything else was the same. Passed in the current rotation to the Jcrop object when it was initialized and I applied Dan's rotation css class to the .jcrop-holder element.

Balcke answered 23/1, 2015 at 16:57 Comment(0)
C
0

Please take look at this. This is working perfectly fine. Thanks to ergoli. I used my logic on the top of ergoli's updated JCrop file. https://github.com/prijuly2000/Image-RotateAndCrop-app

Editted to add the JS code :

var jcrop_api;
var angle = 0;

function checkCoords() {
    if (parseInt($('#w').val())) return true;
    alert('Please select a crop region then press submit.');
    return false;
};

function rotateLeft() {
    angle -= 90;
    $(".jcrop-holder").rotate(angle);
    jcrop_api.setOptions({
        rotate: angle < 0 ? 360 + angle : angle
    });
    if (angle <= -360) angle = 0;
}

function rotateRight() {
    angle += 90;
    $(".jcrop-holder").rotate(angle);
    jcrop_api.setOptions({
        rotate: angle
    });
    if (angle >= 360) angle = 0;
}

function updateCoords(c) {
    $('#x').val(c.x);
    $('#y').val(c.y);
    $('#w').val(c.w); 
    $('#h').val(c.h);
    $('#d').val(angle);
};

function showImage(input) {
    if (input.files && input.files[0]) {
        var reader = new FileReader();
        reader.onload = function(e) {
            $("#image").attr("src", e.target.result).Jcrop({
                onChange: updateCoords,
                onSelect: updateCoords,
                boxWidth: 450,
                boxHeight: 400
            }, function() {
                jcrop_api = this;
            });
        };
        reader.readAsDataURL(input.files[0]);
    }
}
Cornstarch answered 4/2, 2016 at 19:50 Comment(1)
Can you please post some code here to answer the question without relying on external links?Madagascar

© 2022 - 2024 — McMap. All rights reserved.