Creating a Custom Animation Effect in Flex 4

by David Salahi on December 19, 2010

As I discussed in my previous post “O’Reilly’s Flex 4 Cookbook Continues to Disappoint” I recently was frustrated when looking there for sample code to create a Flex 4 custom effect. The Adobe docs have some information on their page “About creating a custom effect” but some of the details are missing, particularly if you want to create an effect based on the Spark Animate class. When I found example 11.8 “Create Custom Animation Effects” in the Flex 4 Cookbook I thought I’d found the info I needed since the sample code on p. 308 shows a class extending Animate. However, I soon found that the code presented on pp. 308-310 is a confusing mish-mash of Flex 3 and Flex 4 that doesn’t even compile. I’ll spare you the gory details here. But if you’re really interested, see my previous post.

Here, I’ll share the code I eventually created to create a custom effect by extending the Flex 4 Animate and AnimateInstance classes. As discussed on the Adobe page mentioned above, you need to write two classes to create a custom animation class. One class is the factory class which the Flex framework uses to create an instance of your animation effect. The other is the class which implements your custom animation. It’s pretty easy once you figure out the basic outline. Here’s my factory class:

public class CustomAnimateEffect extends Animate {
	public var finalAlpha:Number;
	public function CustomAnimateEffect (target:Object=null) {
		super(target);
		this.instanceClass = CustomAnimateInstance;
	}
 
	// create our new instance
	override protected function initInstance(instance:IEffectInstance):void {
		super.initInstance(instance);
		CustomAnimateInstance(instance).finalAlpha = this.finalAlpha;
	}
 
	override public function getAffectedProperties():Array {
		return ["alpha"];
	}
}

The first thing you have to do is provide the effect factory with the name of your effect class. This is done here in the constructor where instanceClass is set. Then you have to set the properties to be animated in the override of initInstance. In this case, I’m only setting the end value finalAlpha. As you’ll see below, this demo effect starts at whatever alpha the target is currently set to.

You could also set multiple properties and animate them all which is where a custom effect could really become useful. Of course, you could also do that with a Parallel or Sequence object. But with a custom effect you have more flexibility to animate whatever you want in whatever way you want. So, for example, you might choose to animate a target object’s alpha value uniformly throughout the effect’s duration but then wait to start animating its color until 50% of the duration has elapsed. Then, you could animate the color change twice as fast during the remaining half the duration. (OK, you could probably do that with a Sequence and a startDelay but you get the idea.)

To complete the two required classes here’s the code for the custom animation:

public class CustomAnimateInstance extends AnimateInstance{
	public var finalAlpha:Number = -1;
 
	public function CustomAnimateInstance(target:Object) {
		super(target);
	}
 
	override public function play():void {
		var motionPath:SimpleMotionPath = new SimpleMotionPath("alpha");
		motionPath.valueFrom = (target as DisplayObject).alpha;
		motionPath.valueTo = finalAlpha == -1 ? 1 : finalAlpha;
		motionPaths = new Vector.<MotionPath>;
		motionPaths.push(motionPath);
 
		super.play();
	}
 
	override public function animationUpdate(animation:Animation):void {
		(target as DisplayObject).alpha = animation.currentValue.alpha as Number;
	}
}

Here, we override a couple of the methods from IAnimationTarget. Most of the code simply creates a SimpleMotionPath which is required by the Animate class. The Animate class calculates the tweened value for you at each frame. Note that the motion path must be created in the play method and not the constructor. This is because the finalAlpha value doesn’t get set until the effect begins to play. That’s when CustomAnimateEffect’s initInstance  method is called and that’s where the desired value gets passed in from the client code. And, here’s that client code:

<fx:Declarations>
	<local:CustomAnimateEffect id="customEffect" finalAlpha="1" target="{btn2}" /> 
</fx:Declarations>
<s:VGroup gap="10" paddingTop="10" paddingLeft="10">
	<s:Button label="Click to fade in the button below" click="customEffect.play()"/>
	<s:Button id="btn2" label="Fade Me In" fontSize="50" alpha="0.2"/>
</s:VGroup>

Download the source code for the custom Flex 4 animation effect (fxp).

{ 3 comments… read them below or add one }

smithfox January 18, 2011 at 1:52 pm

Good article! I translated it into Chinese.
http://www.smithfox.com/?e=63

sunix February 13, 2011 at 6:00 am

Very Thanks.I have a question that I want to display a custom MovieCilp,can you teach me ? Thanks agin.

Mark Fox March 23, 2011 at 11:25 am

Thank You. This is just what I needed.

Leave a Comment

 

{ 4 trackbacks }

Previous post:

Next post: