I’ve had that exact task numerous time while scripting actionscript. I have a source image loaded externally or a mc within the program and I need to fit it into a certain area (width x height) but keep the aspect ratio the same or as photoshop calls it “constrain proportions”. I’ve done this with fancy and not so fancy formulas and equations, but finally I had it and created a simple function that would do it every time. Figured it was worth sharing cause if I’ve googled it before then others most likely will too!
This is more than just setting the width and height of an object, because that way the image is easily skewed and the natural proportions are messed up. If you want to just use scale you need to know the dimensions of the image being resized, and that’s just not scalable (no pun intended).
What we have to do is to do both. Assign the width and height to skew it, and then scale it to correct the proportion. So if we want to resize an image when we don’t know it’s current size to fit into a 300 pixel square we set the width and height of that image to 300 and then a bit of logic that can be summed up in one line:
mc.scaleX < mc.scaleY ? mc.scaleY = mc.scaleX : mc.scaleX = mc.scaleY;
That says if the x scale is larger than the y scale set the x to the y scale amount, and vice versa. It's basically setting both scales to the smaller of the two. This works because we don't know the original size of the image, but actionscript does. scaleX and scaleY are ratios of the current width and height to the originals. A little complicated I know, but that's why I've made the function below. I know how to use it and now I don't have to think about skewing and then scaling back to keep my aspect ratio or proportion. You should see how to use it just by looking at it:
resizeMe(mc:MovieClip, maxW:Number, maxH:Number=0, constrainProportions:Boolean=true)
Pass in the movieClip you want to resize, and the size you want it to fit into. So with the same example above, just do
resizeMe(image, 300);
Example
Here's an interactive example to show what I mean. It loads an external image and you click and drag the mouse around to resize it. To toggle whether you want to constrain proportions use the space bar. Type a url to any image you want to test it with and press load, or hit 'enter'.
[kml_flashembed fversion="9.0.0" movie="https://circlecube.com/circlecube/wp-content/uploads/sites/10/2009/01/constrainproportions.swf" publishmethod="dynamic" width="550" height="550"]
[/kml_flashembed]
Here's a screenshot of me playing with a photo in here NOT constraining proportions.
Source (AS3)
The resizing function
[cc lang="actionscript"]
//The resizing function
// parameters
// required: mc = the movieClip to resize
// required: maxW = either the size of the box to resize to, or just the maximum desired width
// optional: maxH = if desired resize area is not a square, the maximum desired height. default is to match to maxW (so if you want to resize to 200x200, just send 200 once)
// optional: constrainProportions = boolean to determine if you want to constrain proportions or skew image. default true.
function resizeMe(mc:MovieClip, maxW:Number, maxH:Number=0, constrainProportions:Boolean=true):void{
maxH = maxH == 0 ? maxW : maxH;
mc.width = maxW;
mc.height = maxH;
if (constrainProportions) {
mc.scaleX < mc.scaleY ? mc.scaleY = mc.scaleX : mc.scaleX = mc.scaleY;
}
}
[/cc]The full source
[cc lang="actionscript"]
var defaultUrl:String = "https://circlecube.com/circlecube/wp-content/uploads/sites/10/2008/11/circlecubelogo4.png";
var image:MovieClip = new MovieClip();
loadImage();
function loadImage(url:String=""):void {
if (url == "" || url == defaultToLoadString) url = defaultUrl;
//clear image
image.visible = false;
image = new MovieClip();
//add image
var ldr:Loader = new Loader();
var urlReq:URLRequest = new URLRequest(url);
trace("loading image: " + url);
ldr.load(urlReq);
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, imageCompleteHandler);
image.addChild(ldr);
addChild(image);
}function imageCompleteHandler(e:Event):void {
resizeMe(image, stage.stageWidth)
}//The resizing function
// parameters
// required: mc = the movieClip to resize
// required: maxW = either the size of the box to resize to, or just the maximum desired width
// optional: maxH = if desired resize area is not a square, the maximum desired height. default is to match to maxW (so if you want to resize to 200x200, just send 200 once)
// optional: constrainProportions = boolean to determine if you want to constrain proportions or skew image. default true.
function resizeMe(mc:MovieClip, maxW:Number, maxH:Number=0, constrainProportions:Boolean=true):void{
maxH = maxH == 0 ? maxW : maxH;
mc.width = maxW;
mc.height = maxH;
if (constrainProportions) {
mc.scaleX < mc.scaleY ? mc.scaleY = mc.scaleX : mc.scaleX = mc.scaleY;
}
}var constrainOn:Boolean = true;
var isPressed:Boolean = false;stage.addEventListener(MouseEvent.MOUSE_MOVE, moved);
stage.addEventListener(MouseEvent.MOUSE_DOWN, pressed);
stage.addEventListener(MouseEvent.MOUSE_UP, released);
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownListener);function keyDownListener(e:KeyboardEvent) {
if (e.keyCode == 32){//spacebar
toggled(e);
}
if(e.keyCode == 13){//enter
loadImagePress(e);
}
}function moved(e:Event):void{
if (isPressed)
resizeMe(image, mouseX, mouseY, constrainOn);
}
function pressed(e:MouseEvent):void{
isPressed = true;
moved(e);
}
function released(e:MouseEvent):void{
isPressed = false;
}
function toggled(e:Event):void{
constrainOn = !constrainOn;
moved(e);
}
var defaultToLoadString:String = "type url of image to load";
toLoad.text = defaultToLoadString;
toLoad.addEventListener(FocusEvent.FOCUS_IN, toLoadFocus);
toLoad.addEventListener(FocusEvent.FOCUS_OUT, toLoadBlur);
function toLoadFocus(e:FocusEvent):void{
if (toLoad.text == defaultToLoadString)
toLoad.text = "";
}
function toLoadBlur(e:FocusEvent):void{
if (toLoad.text == "")
toLoad.text = defaultToLoadString;
}
loadBtn.addEventListener(MouseEvent.CLICK, loadImagePress);
function loadImagePress(e:Event):void{
loadImage(toLoad.text);
}
[/cc]
Download
And as usual, let me know if you've got any comments questions or suggestions! Thanks,