Dec 27

Center Registration Point - Another Recipe for the Flex CookBook

Here’s a little recipe for scaling an image from a center registration point. Flash always allowed you to bounce the registration point wherever you wanted, but Flex expects it on the top left. If you want to resize an image from the center evenly, with a horizontal slider for example, you’ll like this one.

First the MXML. This layout is simple, it basically just has the small script with a function to accept a SilderEvent when the user changes the value of the horizontal slider. This function then uses the static functions (calcX() and calcY()) in the ImageResizer class to calculate the new math and tell your image how to resize properly from the center.

Your layout

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
	<mx:Script>
		<![CDATA[
			import mx.events.SliderEvent;
			import utils.DefaultValues;
			import utils.ImageResizer;			
 
			public function doChangeSize(event:SliderEvent):void{
				// get the value of the hSlider, round it and divide by 100 for consistency
				var multiplier:Number = Math.round(hSlider.value) / 100;
				//trace(multiplier);
				// new height, width, x, and y for image
				img.width = DefaultValues.maxImageWidth * multiplier;
				img.height = DefaultValues.maxImageHeight * multiplier;				
				img.x = ImageResizer.calcX(container.x,container.width,img.width);
				img.y = ImageResizer.calcY(container.y,container.height,img.height);
 
				// to avoid a "jump in position", find out where the full image's x,y coords are when the slider is
				// at 100% and place the image at those coords within it's parent container
				trace(img.x + " " + img.y);
			}
		]]>
	</mx:Script>
 
	<mx:Canvas width="500" horizontalScrollPolicy="off" verticalScrollPolicy="off" height="500" id="container">
		<mx:Image id="img" source="@Embed('assets/images/pxl_white_logo.jpg')" x="161" y="199"/>
		<mx:HSlider id="hSlider"
			minimum="0" maximum="100" 
			tickColor="black" 
			value="100"
			liveDragging="true" 
			thumbDrag="doChangeSize(event)" width="339" x="80" y="335" 
			showTrackHighlight="true" 
			themeColor="#ff8c00"/>
	</mx:Canvas>
 
</mx:Application>

The comments should be self explanatory enough. The “view” consists of a Canvas to hold your components, the image itself and the horizontal slider. When the slider thumb changes, it calls the doChangeSize() function which will make use of the ImageResizer class’ static functions.

ImageResizer class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package utils
{
	import utils.DefaultValues;
 
	public class ImageResizer {
		/**
		 *  Calculate your new center registration point. calcX wants x, containerWidth, and w.
		 *  Those are your image's parent container x, and width, and then your image's width.
		 *
		 * */
		public static function calcX (x:Number,containerWidth:Number,w:Number) : Number {
			// half of image's parent containers width
			var newRegX:Number = Math.round((w / 2));
			// parent container's x minus your new registration X
			var newX:Number = Math.round(x - newRegX);
			// value for the default parent container's width divided by 2
			var center:Number = Math.round(DefaultValues.innerCanvasWidth/2);
			// return your new centered X
			return Math.round(newX += center);
		}
		public static function calcY (y:Number,containerHeight:Number,h:Number) : Number {
			var newRegY:Number = Math.round(h / 2);
			var newY:Number = Math.round(y - newRegY);
			var center:Number = Math.round(containerHeight / 2);
			return Math.round(newY += center);
		}
	}
}

calcX() and calcY() will accept the image’s parent container’s x, y, width and height, as well as the image’s width and height. The functions will then calculate a new registration point (x and y) based on the information given them. The comments in the code should be clear enough.

In this recipe, we make use of the DefaultValues class to hold some constants for us, like the image’s container width, and the image’s full width and height. It’s not imperative that we maintain this convention, but it does keep things separated and clean. This class does nothing more than maintain these values for us.

DefaultValues class

1
2
3
4
5
6
7
8
9
package utils {
 
	public final class DefaultValues {
 
		public static const innerCanvasWidth:int = 500;// width of your image's parent container
		public static const maxImageHeight:int=102;//height of full image
		public static const maxImageWidth:int=177;//width of full image
	}
}

Sample

You can now play with the slider and resize the image from it’s new centered registration point. Because we set the horizontal slider’s liveDragging property to true, and the thumbDrag property to update every change in the thumb’s position, we can resize the image in real time. There are many other uses for the ImageResizer class, this is just one quick and simple little recipe I thought I’d share. Manga!

Download source code
resizefromcenter.zip

[flash http://www.davidflatley.com/wp-content/uploads/2007/12/resizefromcenter.swf o={height="500" width="500"}]

Technorati Tags: , , , , , , ,

2 Comments so far

  1. Aleks March 3rd, 2008 3:27 am

    It has a bug. If i do not move triangle, but i click on scroll line the picture will be not resized

  2. Dave March 3rd, 2008 1:55 pm

    Hi Aleks,
    I actually never put in the code for the track click as it’s just a quick sample to show the resize from center. But if you want the pic to change on track click, just add this line to the HSlider in the ResizeFromCenter.mxml (around line 33 or anywhere inside the HSlider).

    change=”doChangeSize(event)”

    problem solved :)

Leave a comment