6
\$\begingroup\$

I was looking for a function which would take the overall width, max height, min height parameters as the input and fit multiple images in the given overall width adjusting their width.

For an example in this page, all the images (in the same row) should get auto-adjusted to the same height, keeping their original aspect ratio with JavaScript changing their widths.

Is there a simple and better way to do this?

The solved example page is here.

$(function(){
//var pics;
var pic1 = {height:"10", width:"20", ap:1.374, rh:0};
var pics = [pic1];
//pics.push(pic3);
//$('#test').html(pics[2].height);
$('#some').imagesLoaded(function() {
$('#test').html('test ');
$('#some img').each(function(index) { 
 //setting const height
 $(this).height(150);
 var apic = {height:$(this).height() , width: $(this).width() ,ap: $(this).width() / $(this).height() , rh:0};
 pics.push(apic);
});
$('#test').append(pics.length+ '<br />');
for (var j=1; j <pics.length;j++) {
 $('#test').append(pics[j].width + ' ' + pics[j].ap + '<br />');
}
$('#test').append('Calculating width ' + '<br />');
var set = [0];
for (var j=1; j <pics.length;j++) {
 var t = 0;
 var c = j
 do { 
 t = t+ pics[c].width;
 $('#test').append(c + ' ' + t+ '<br />');
 c=c+1;
 }while (t < 645 && c<pics.length);
 c=c-1;
 if(t>645) {
 c = c -1;
 }
 set.push(c);
 j = c;
} 
$('#test').append('Sets are: <br />');
var v = 1;
var st = 0;
for (p = 1; p<set.length; p++) {
 $('#test').append(set[p] + ' '); 
 st = v;
 v = set[p];
 $('#test').append(p + ': ');
 var tot = 0;
 var inc = 0;
 while(tot < 645 ) {
 var tot1=0;
 for(var g = st; g<v+1; g ++) {
 tot1 =tot1+ (pics[g].ap * (pics[g].height+inc));
 }
 tot=tot1;
 inc = inc+1;
 }
 for(var g = st; g<v+1; g ++) {
 $('#some img').eq(g-1).height ( 150 + inc); 
 }
 $('#test').append( '<br / >');
 v = v+1;
}
$('#test').append('<br />'); 
/*
var tot = 0
var wid;
var wid1;
var inc=0;
var r = 1;
for (r =1; r<pics.length-1; r++) {
 inc = 0;
 tot = 0;
while ( tot < 645) {
 wid = pics[r].ap * (pics[r].height+inc);
 wid1 = pics[r+1].ap * (pics[r+1].height+inc);
 tot = wid + wid1;
 inc = inc+ 1;
}
$('#test').append('Total ' + inc +' '+ wid + ' ' + wid1 + '<br />'); 
$('#some img').eq(r-1).height ( 150 + inc);
$('#some img').eq(r).height ( 150 + inc);
 r=r+1;
 */
}
 );
});
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Nov 26, 2016 at 18:25
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Fit images to width.

To make n images fit a width while keeping each image's aspect do the following.

  • Get the height that the images need to be to fit.
// images is an array of loaded images
// width is the width to fit
// returns the height images must be to fit.
function getFitSize(images,width){
 var totalWidth = 0; // Holds the total aspect width
 // sum aspect for each image for total aspect width
 images.forEach(img=>{
 totalWidth += img.width / img.height;
 })
 // then get height to fit the required width
 return width / totalWidth; // the height for all to fit
}
var height = getFitSize(images,500); // fit images to 500 pixels across

With the height you just need to use that to scale the width by the aspect and set the height.

  • Size each image.
image.width = height * (image.width / image.height); // the image width that
 // will fit
image.height = height;

Example

A Javascript example showing usage of above method. Images are loaded one at a time and made to fit the available page width.

const imageURLList = [ "https://upload.wikimedia.org/wikipedia/commons/thumb/5/52/Renaissance_Center%2C_Detroit%2C_Michigan_from_S_2014年12月07日.jpg/380px-Renaissance_Center%2C_Detroit%2C_Michigan_from_S_2014年12月07日.jpg",
"https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Paulus_Moreelse_-_Zelfportret.jpg/300px-Paulus_Moreelse_-_Zelfportret.jpg",
"https://upload.wikimedia.org/wikipedia/en/thumb/b/bb/Maull_%26_Fox_-_Fanny_Bullock_Workman.jpg/300px-Maull_%26_Fox_-_Fanny_Bullock_Workman.jpg",
"https://upload.wikimedia.org/wikipedia/commons/thumb/7/79/Toompea_loss_2014.jpg/380px-Toompea_loss_2014.jpg",
"https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/Winslow_Homer_-_The_Gulf_Stream_-_Metropolitan_Museum_of_Art.jpg/350px-Winslow_Homer_-_The_Gulf_Stream_-_Metropolitan_Museum_of_Art.jpg"
];
const images = [];
function getFitSize(images,width){
 var totalWidth = 0; 
 images.forEach(img=>{ totalWidth += img.naturalWidth / img.naturalHeight })
 return width / totalWidth; 
}
// load images one at a time for effect only
function loadImage(){
 const image = new Image;
 image.src = imageURLList.shift();
 image.onload = function(){
 images.push(image);
 const width = imageContainer.getBoundingClientRect().width;
 const height = Math.floor(getFitSize(images,width));
 images.forEach(image => {
 image.style.width = Math.floor(height * (image.width / image.height)) + "px"; 
 image.style.height = height + "px";
 });
 imageContainer.appendChild(image);
 if(imageURLList.length > 0){
 loadingInfo.textContent = "Loading image " + (images.length +1); 
 setTimeout(loadImage,2000);
 }else{
 loadingInfo.textContent = "Loading complete";
 }
 }
}
loadingInfo.textContent = "Loading image " + (images.length +1); 
setTimeout(loadImage,2000);
#imageContainer {width : 100%;}
body { font-family : arial; margin: 0px; overflow: hidden;}
.noEdge {margin: 0px; padding : 0px; }
.atr { font-size : small; }
Fit images to width.<span id="loadingInfo"></span>
<div class="noEdge" id = "imageContainer"></div>
<div class="atr">Images from <a href="https://en.wikipedia.org/wiki/Wikipedia:Picture_of_the_day/January_2017">Wikipedia:Picture of the day/January 2017</a></div>

answered Nov 27, 2016 at 3:11
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.