Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is is possible to generate a percentage center point instead of absolute boundary? #81

Open
lijunle opened this issue Jun 28, 2018 · 3 comments

Comments

@lijunle
Copy link

lijunle commented Jun 28, 2018

Hi, @jwagner

This is an awesome library, thank you for creating it!

I am considering to use the library in production environment, with responsiveness support. However, the absolute cropped boundary numbers are not very friendly to responsiveness. If the calculation result is a center point with percentage, we can use the following CSS styles to stick to that center point, then it will show good in PC view or mobile view.

const style = {
  backgroundImage: `url("${imageURL}")`,
  backgroundPosition: `${centerPoint.x}% ${centerPoint.y}%`
}

Now, I am calculating the central point of the crop result as the center point. That is working but not really accurate.

More ideas?

@lijunle
Copy link
Author

lijunle commented Jun 28, 2018

I found another workaround, set the width=height=50px (or small), minScale=0,5 (or small). It will generate a square cropped area, use the central point of this area as center point. The result is more making sense.

@jwagner
Copy link
Owner

jwagner commented Jun 29, 2018

just take x/width*100 to get %.

@Candyffm
Copy link

Candyffm commented Aug 27, 2021

Here is the full code to convert the crop to css background-position:

var img = document.getElementById('imgId');

// adjust settings to your needs
smartcrop.crop(img, {
    width    : 100,
    height   : 100,
    minScale : .75
}).then(function(result) {
    var crop    = result.topCrop;

    var X_total = img.naturalWidth - crop.width; 
    var X_perc  = crop.x/X_total;

    var Y_total = img.naturalHeight - crop.height;
    var Y_perc  = crop.y/Y_total;

    var cssBgPos = (X_perc*100).toFixed(0) + '% ' + (Y_perc*100).toFixed(0) + '%');

    // your code...
});

Personally I only use background-size: cover; in my projects. To find the best fit for multiple target aspect ratios I calculate two crops with an ratio of 3:2 (for the y-axis) and 2:3 (for the x-axis) and translate these crops to background-position values. My complete code looks like this:

// calculate best crops for 3:2 and 2:3
var img = document.getElementById(imgId);
var naturalWidth  = img.naturalWidth;
var naturalHeight = img.naturalHeight;

// smart crop for 3:2 (y-axis)
smartcrop.crop(img, {
    width    : 300,
    height   : 200,
    minScale : 1 // due to background-size:cover;
}).then(function(result) {
    var crop    = result.topCrop;

    // calc max value for crop.y given the height of the crop, this represents
    // 100% in terms of css background-position for the y-axis
    var Y_total = naturalHeight - crop.height;

    // calculate actual css background-position for the y-axis
    var Y_perc  = crop.y/Y_total;

    // smart crop for 2:3 (x-axis)
    smartcrop.crop(img, {
        width    : 200,
        height   : 300,
        minScale : 1 // due to background-size:cover;
    }).then(function(result) {
        var crop    = result.topCrop;

        // calc max value for crop.x given the width of the crop, this represents
        // 100% in terms of css background-position for the x-axis
        var X_total = naturalWidth - crop.width;
       
        // calculate actual css background-position for the x-axis
        var X_perc  = crop.x/X_total;

        var cssBgPos = (X_perc*100).toFixed(0) + '% ' + (Y_perc*100).toFixed(0) + '%';
        // cssBgPos is what I work with then
    });
});

If you only have one img ratio, you do not need to calculate multiple ratios, but this method works pretty well for varying ratios. You might want to use more extreme ratios like 2:1 and 1:2 if you have to cover a wider spectrum.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants