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...
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.
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
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! :)
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.