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,
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.
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.
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!
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
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]);
}
}
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.