Scale to Fit (or Zoom to Fit)

This is a seemingly trivial task, but attempt to tackle it and you’ll quickly find yourself scratching your head wondering what the hell you’re doing…


Now, I’ve had to build scaling items before, and each time I end up starting from scratch because my last implementation was rather repulsive.

Once again, I set out to build this component, only to remember how much of a PITA it is. As I set out upon my search I quickly realized that there wasn’t a whole bunch of information on the topic (or my google-fu was weak today). I saw a ton of references to how to scale in HTML/CSS (duh, set it to 100% width and height, you weaksauces) but I was doing something a lot more complicated. I needed to be able to change the scale of my child at-will in a non-child-sizing container… Well, that and I’m not using HTML – but that matters very little.

I actually managed to stumble across a few implementations; but most didn’t account for every possible size (i.e., container larger than child, child wider than taller, and all permutations of such), and were more unprepossessing than my own implementation.

After studying a few implementations, I came up with the following code:

public static function calcScaleToFitRatio(parentObj:DisplayObject, childObj:DisplayObject):Number
{
  var retVal:Number = 1;

  if (null == childObj) {
    return 1;
  }

  var containerRatio:Number     = parentObj.height  / parentObj.width;
  var contentsRatio:Number      = childObj.height   / childObj.width;
  var isContainerLarger:Boolean = (containerRatio > contentsRatio);

  if (true === isContainerLarger) {
    //if container ratio is larger
    retVal = parentObj.width / childObj.width;
    // ... scale based on widths
  } else {
    //else contents are larger
    retVal = parentObj.height / childObj.height;
    // ... scale based on heights
  }

  return retVal;
}

Most of it should be really obvious, but there’s a few interesting things to note:

First and foremost, is the order in which you determine the aspect ratios. It really doesn’t matter which order you calculate (height / width vs width / height) as long as you evaluate both the child and parent in the same order. Reversing the order in this logic will also require the “greater than” expression to flip to “lesser than.”

The calculation of retVal above is pretty self-explanatory; you essentially scale based on the width if the container is a larger aspect ratio (again, assuming height / width as depicted in code-block above).

Next time I need to build such a component, I won’t be scratching my head bald trying to find out why something so simple-sounding is still kicking my ass after an hour.

[EDIT]
I forgot to mention that I set this up as a utility method, and it returns the scale ratio. In Flex, we have the scaleX and scaleY property which I’m currently using. Otherwise you just multiply your child’s height/width by the scale factor, and everything should go as planned. If not, double check order of your expressions.

Advertisements

About killerspaz

I'm a developer that loves to tinker with cutting edge technology. I have recently been playing with the Flash Platform (AS3/Flex), Android (custom roms, replacement apps, scripting), and looking at opportunities in the mobile markets.

Posted on 07.14.2010, in Flash, Flex and tagged , , , , , , . Bookmark the permalink. 1 Comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: