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;
  */
}
  );




});
\$\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>

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.