Javascript fill within container while maintaining aspect ratio

I’ve been working with the jQuery plug-in jCrop to let users adjust thumbnails to focus on the object of their photos. The photo may vary in ratio and size, also the location of the important object of the photo may not be in the center of the original image file. This is not an automation-friendly scenario and we need the user to help us get the thumbnails look good.

Warning! This code is not tested with a different thumb-ratio (variable “ratio”) as my intended need is locked at this ratio forever..

I will only display the javascript code here. Please refer to my jsFiddle project for the html and css code.

Simple fill within a parent container

var height = $('#target').css('height').replace('px', '');
var width = $('#target').css('width').replace('px', '');

var ratio = 22/17;

var selectWidth = width;
var selectHeight = height;

if ((width/height) > ratio){
  selectWidth = Math.round(selectHeight * ratio);
} else if ((width/height) < ratio){
  selectHeight = Math.round(selectWidth / ratio);
}

$('#selection').height(selectHeight);
$('#selection').width(selectWidth);

First we get the height and width of the parent container div.

– Next we define the ratio. My thumb is 220px wide and 170px high so the ratio breaks down to 22/17

– In the if we check if the ratio of the container is higher than the ratio of our thumb. Lets say the container is very wide and not very high. Then we can safely set the height of the child div to the height of the container (as long as the ratio of the thumb allows it) and calculate the width based on the width AND ratio.

– If, on the other hand, the container is very high and not very wide (relative to the thumb ratio), we can set the width of the child div to the width of the container and calculate the height.

– Notice that we use an else if and not a simple else. The reason is that if the ratio of the container is exactly the same as the thumb (could happen I guess..) the child div is simply exactly as large as the container.

This is all good, but lets say a user uploads an image which is very “tall”. We would guess the relevant object of the photo is in the center, at least it would look better to suggest a crop in the center of the photo. Also we might want to add a bit of padding. Just to make the selection area a little more slick and obvious for the user.

Check out the complete code for a centered and padded version at jsFiddle.

Fill within a parent container centered and padded

var height = $('#target').css('height').replace('px', '');
var width = $('#target').css('width').replace('px', '');

var ratio = 22/17;

var selectWidth = width;
var selectHeight = height;

var padding = 5;

if ((width/height) > ratio){
  selectHeight = height - (padding * 2);
  selectWidth = Math.round(selectHeight * ratio);
  $('#selection').css('top', padding + 'px');
  $('#selection').css('left', (((width-selectWidth)/2)-padding) + 'px');
} else if ((width/height) < ratio){
  selectHeight = Math.round(selectWidth / ratio);
  selectWidth = width - (padding * 2);
  $('#selection').css('top', (((height-selectHeight)/2)-padding) + 'px');
  $('#selection').css('left', padding + 'px');
} else {
  selectHeight = height - (padding * 2);
  selectWidth = width - (padding * 2);
  $('#selection').css('top', padding + 'px');
  $('#selection').css('left', padding + 'px');
}

$('#selection').height(selectHeight);
$('#selection').width(selectWidth);

This is a little bit different. We reduce the height and with of the child div to accommodate the padding and we to some very obvious math to place the child div relative to the parent container.

Note that we do need a simple else here to simply reduce both the height and with of the child div and place it half a “padding” down and half a “padding” to the left.

I hope this makes sense and saves you some time.

  1. No comments yet.

  1. No trackbacks yet.