Since jcrop is now working on touch screens I want to do a web app that uses it. I have everything working on it but if I try to make the design responsive so that the user can see the whole image before cropping (it's width is a percentage of the screen) then the cropped area won't be the same as the selected by the user. The coordinates of the selection made on top of the resized image won't match the ones on the full size image.
Jcrop includes a solution to a similar issue (when handling huge images) by using box sizing or the truesize method but none of them work if the width of the image is based on percentages, instead of a given width in pixels.
The only solution I can think of is to resize the image using media queries and make 3 or 4 versions depending on the width of the screen but I'd rather stick to the percentage based resize because it looks much better.
This is my jcrop call:
var jcrop_api, boundx, boundy;
$('#target').Jcrop({
onChange: updatePreview,
onSelect: updatePreview,
aspectRatio: 0.75
},function(){
// Use the API to get the real image size
var bounds = this.getBounds();
boundx = bounds[0];
boundy = bounds[1];
trueSize: [900,600],
// Store the API in the jcrop_api variable
jcrop_api = this;
});
function updatePreview(c){
if (parseInt(c.w) > 0){
var rx = <?echo $width;?> / c.w;
var ry = <?echo $height;?> / c.h;
$('#preview').css({
width: Math.round(rx * boundx) + 'px',
height: Math.round(ry * boundy) + 'px',
marginLeft: '-' + Math.round(rx * c.x) + 'px',
marginTop: '-' + Math.round(ry * c.y) + 'px'
});
}
$('#x').val(c.x);
$('#y').val(c.y);
$('#w').val(c.w);
$('#h').val(c.h);
};
TrueSize ended up doing the trick, I wasn't using it properly:
jQuery(function($){
// Create variables (in this scope) to hold the API and image size
var jcrop_api, boundx, boundy;
$('#target').Jcrop({
onChange: updatePreview,
onSelect: updatePreview,
aspectRatio: 0.75,
trueSize: [<?echo $width2;?>,<?echo $height2;?>]
},function(){
// Use the API to get the real image size
var bounds = this.getBounds();
boundx = bounds[0];
boundy = bounds[0.75];
//trueSize: [ancho,alto],
// Store the API in the jcrop_api variable
jcrop_api = this;
});
function updatePreview(c){
if (parseInt(c.w) > 0){
var rx = <?echo $width;?> / c.w;
var ry = <?echo $height;?> / c.h;
$('#preview').css({
width: Math.round(rx * boundx) + 'px',
height: Math.round(ry * boundy) + 'px',
marginLeft: '-' + Math.round(rx * c.x) + 'px',
marginTop: '-' + Math.round(ry * c.y) + 'px'
});
}
$('#x').val(c.x);
$('#y').val(c.y);
$('#w').val(c.w);
$('#h').val(c.h);
};
});
It worked with the following code
var width2 = jQuery('#cropbox').prop('naturalWidth');
var height2 = jQuery('#cropbox').prop('naturalHeight');
jQuery('#cropbox').Jcrop({
aspectRatio: 1,
onSelect: updateCoords,
onChange: updateCoords,
setSelec: [0,0,110,110],
trueSize: [width2,height2]
});
I hope even my answer would help people to get the idea. Lets say we are having a responsive image in bootstrap with class img-responsive
Here is the html form with image in it
<form method="POST" action="#" enctype="multipart/form-data">
<img class="img-responsive" id="get-profile-img" src="image.jpg"/>
<input id="x" name="x" type="hidden" value="">
<input id="y" name="y" type="hidden" value="">
<input id="w" name="w" type="hidden" value="">
<input id="h" name="h" type="hidden" value="">
<input id="rx" name="rx" type="hidden" value="">
<input id="ry" name="ry" type="hidden" value="">
<input id="rw" name="rw" type="hidden" value="">
<input id="rh" name="rh" type="hidden" value="">
</form>
Here is the JCrop code which will get rx, ry, rw and rh based on calculations of x, y, w and h
$(function() {
$('#get-profile-img').Jcrop({
onSelect: updateCoords,
aspectRatio: 1,
setSelect : [50, 0, 300,300],
allowResize: true
});
});
function updateCoords(c) {
$('#x').val(c.x);
$('#y').val(c.y);
$('#w').val(c.w);
$('#h').val(c.h);
responsiveCoords(c, '#get-profile-img');
};
function responsiveCoords(c, imgSelector) {
var imgOrignalWidth = $(imgSelector).prop('naturalWidth');
var imgOriginalHeight = $(imgSelector).prop('naturalHeight');
var imgResponsiveWidth = parseInt($(imgSelector).css('width'));
var imgResponsiveHeight = parseInt($(imgSelector).css('height'));
var responsiveX = Math.ceil((c.x/imgResponsiveWidth) * imgOrignalWidth);
var responsiveY = Math.ceil((c.y/imgResponsiveHeight) * imgOriginalHeight);
var responsiveW = Math.ceil((c.w/imgResponsiveWidth) * imgOrignalWidth);
var responsiveH = Math.ceil((c.h/imgResponsiveHeight) * imgOriginalHeight);
$('#rx').val(responsiveX);
$('#ry').val(responsiveY);
$('#rw').val(responsiveW);
$('#rh').val(responsiveH);
};
Finally at PHP side take rx, ry, rw and rh instead of x, y, w and h.
(or)
You can simply override the
rx, ry, rw and rh
on
x, y, w and h like this and use x, y, w and h as usual.
$('#x').val(responsiveX);
$('#y').val(responsiveY);
$('#w').val(responsiveW);
$('#h').val(responsiveH);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With