Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using jcrop on responsive images

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);

    };
like image 885
Elaine Marley Avatar asked Nov 30 '12 15:11

Elaine Marley


3 Answers

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);

    };


});
like image 96
Elaine Marley Avatar answered Nov 07 '22 06:11

Elaine Marley


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]
});
like image 30
AirKoKo Avatar answered Nov 07 '22 08:11

AirKoKo


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);
like image 1
Mohd Samiullah Avatar answered Nov 07 '22 07:11

Mohd Samiullah