Javascript Image Resize Calculation

2019-05-27 05:18发布

问题:

Let's say I have an image that is 1920 x 1280.

I'm using a slider to scale down the image, which goes from 100% to 0%, where 100% is the original size and 0% is the minimum size.

The image can be no smaller than 350 in either height, or width, so 0% should equate to this minimum size.

What formula would I use to calculate the new dimensions? If you could explain the logic, that would be helpful.

I'm certain this is an SAT question that I failed...

回答1:

var min=Math.min(width,height);
var result=Math.max(min * (percentage/100),350);
var newHeight=(result/min) * height;
var newWidth=(result/min) * width;

Percentage between 0 and 1 (can be altered to be 0 - 100 integers instead of 0 to 1 floats). Other words are describing themselves. Maybe useful as a function:

function ff(height,width,percentage){    
    var min=Math.min(width,height);
    var result=Math.max(min*(percentage/100),350);
    var newHeight=(result/min) * height;
    var newWidth=(result/min) * width; 
    return [newWidth,newHeight]; 
 }

No math is needed for this. Css is already capable of these things.

min-width: 350px;
min-height:350px;
width: x% (or height: ... x%)
in a 1920 by 1280 sized div.


回答2:

ok. to calculate the image resizing you can use the following calculation: Max width: 1920 Max height: 1280

width Min: ? height Min: 350

1280 - 350 = 930 930/100 = 9.3 1% equals 9.3px

1920 - 1280 = 640 350 + 640 = 990

new minimum width = 990

1920 - 990 = 930 930/100 = 9.3

1% equal to 9.3

then you will have to use the 9.3 pixel value for every 1%

if you consider that 350 pixel are the minimum values for both dimensions, your image will look strange



回答3:

The method below will re-size an image with a percentage, 0% being a minimum value, and the image keeping aspect ratio:

The best approach would be to create a function, which takes the values x, y, percentage and minimum. Next, create a variable called ratio which is y/x (explained below). Then multiply x (minus minimum, to decrease the range, and therefore make 0% equal 350) by (percentage/100) and y (minus minimum times ratio, to create a different range for y, and therefore maintain aspect ratio) by (percentage/100), and return an array with the re-sized x and y, each plus minimum (and y plus minimum times ratio to compensate for what we did) so 0% is 350 and 233.333, while 100% is 1920 and 1280. If the height is larger than the width, the ratio will be y/x instad of x/y, and minimum will be multiplied by ratio for x, instead of y. Have a look at this code:

resizeImage = function(x,y,percentage,minimum) {
    if (x > y) {
        ratio = y/x;
        rx = (x-minimum)*(percentage/100);
        ry = (y-minimum*ratio)*(percentage/100);
        return [rx+minimum,ry+minimum*ratio];
    } else {
        ratio = x/y;
        rx = (x-minimum*ratio)*(percentage/100);
        ry = (y-minimum)*(percentage/100);
        return [rx+minimum*ratio,ry+minimum];
    }
}

– and run it like this:

resizeImage(1920,1280,0,350);
// returns [350, 233.333]
resizeImage(1920,1280,30,350);
// returns [821, 547.333]

Have a look at this working example, using HTML, JavaScript and jQuery (drag the slider above the image to re-size it):

$(document).ready(function() {

    var w = 518;
    var h = 387;
    var min = 350;

    resizeImage = function(x,y,percentage,minimum) {
        if (x > y) {
            ratio = y/x;
            rx = (x-minimum)*(percentage/100);
            ry = (y-minimum*ratio)*(percentage/100);
            return [rx+minimum,ry+minimum*ratio];
        } else {
            ratio = x/y;
            rx = (x-minimum*ratio)*(percentage/100);
            ry = (y-minimum)*(percentage/100);
            return [rx+minimum*ratio,ry+minimum];
        }
    }

    $("#slider").change(function() {
        p = $("#slider").val();
        $("img").css({width:resizeImage(w,h,p,min)[0],height:resizeImage(w,h,p,min)[1]});
    })
  
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<input type="range" min="0" max="100" value="50" step="1" id="slider" style="width:500;">
<br>
<img src="http://weknowmemes.com/generator/uploads/generated/g1369409960206058073.jpg">

Hope this helps! :)



回答4:

After some tweaking and looking through the provided answers, here's some working code that will adjust for differences in height, width, and aspect ratios. With use of some data attributes, this is a good start to feed from, and if you are using a different form of communicating the data, just replace variables as needed. First, the HTML:

<input type="range" min="0" max="100" value="100" step="1" id="slider" style="width: 500px;" />
<div id="per">100%</div>
<div>
    <img src="http://placehold.it/1920x1280" alt="My image" id="my-img" />
</div>

Simple enough, and when testing, change the src attribute of the img tag to see how the code handles different sizes. Now the fun part:

var id = function(i){return(document.getElementById(i));},
    slider = id('slider'),
    per = id('per'),
    img = id('my-img'),
    d_w = 0,
    d_h = 0,
    min = 350,
    reSize = function(percent) {
        var h = slider.getAttribute('data-h') == 'true',
            s_h = (parseFloat(slider.getAttribute('data-step-h')) * percent) + min,
            s_w = (parseFloat(slider.getAttribute('data-step-w')) * percent) + min,
            o_h = (d_h / d_w) * s_w,
            o_w = (d_w / d_h) * s_h;
        img.style.height = ((h) ? s_h : o_h).toString() + 'px';
        img.style.width = ((h) ? o_w : s_w).toString() + 'px';
    };
img.addEventListener('load', function() {
    d_w = this.width;
    d_h = this.height;
    slider.setAttribute('data-h', (d_w > d_h));
    slider.setAttribute('data-step-h', (d_h - min) / 100);
    slider.setAttribute('data-step-w', (d_w - min) / 100);
    slider.addEventListener('input', function() {
        var perc = parseFloat(this.value);
        per.innerHTML = perc.toString() + '%';
        reSize(perc);
    }, false);
}, false);

Few quick pointers, make sure to wrap this in an onload or better yet, DomContentLoaded method like:

document.addEventListener('DOMContentLoaded', function()( /* Code */ }, false);

And keep in mind the range type of input isn't supported in older IE, some maybe some hidden inputs instead? Also, instead of input in the slider event, it has to be change in IE 10 so keep that in mind for cross browser-ness.

Breakdown of the code, yeah? Alright, first we declare some variables, where id is just to grab by ID, grab the elements, have some more 'global' like variables (d_w, d_h, and min) where d_w is default width and d_h is, yep, default height. The reSize() function grabs the data assigned to the image and uses it for calculations and determining which side is longer, followed by s_h and s_w which uses the step to adjust the pixels, some aspect ratio equations, and finally hit the width and height of the element with CSS.

slider.addEventListener does a few simple things, like update the percent and run the reSize() function when it moves. Again, make sure to check for IE 10 and replace input with change if you want this to work on that... 'browser'.

Finally, the img event grabs the default width and height, assigns them to said variables (d_w and d_h), checks which side is longer, and with the help of Paulo, calculates the step for each percent based on the offset of the actual size vs the minimum. I tested this on Chrome, FF, and IE 10+ and it's working fine. It'll work on IE 9>, but you'll have to use attachEvent and no range element. Hope this helps.

EDIT
I put the slider event within the img load event to prevent premature firing of the code. I could tweak this more and even make it a stand-alone 'class' (well, kinda, JS classes are weird) if you like, let me know and I'd take a swing at it.