Working with effects

Effects have many configuration settings that you can use to control the effect. For example, you can set the effect duration and repeat behavior, or handle effect events. The effect target also has configuration settings that you can use to configure it for effects.

Setting effect durations

All effects take the duration property that you can use to specify the time, in milliseconds, over which the effect occurs. The following example creates two versions of the Fade effect. The slowFade effect uses a two-second duration; the reallySlowFade effect uses an eight-second duration:

<?xml version="1.0"?>
<!-- behaviors\FadeDuration.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">
    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

    <fx:Declarations>
        <s:Fade id="slowFade" 
            duration="2000" 
            target="{myButton1}"/>
        <s:Fade id="reallySlowFade" 
            duration="8000" 
            target="{myButton2}"/>
    </fx:Declarations>

    <s:Button id="myButton1" 
        label="Button 1" 
        creationCompleteEffect="{slowFade}"/>
    <s:Button id="myButton2" 
        label="Button 2" 
        creationCompleteEffect="{reallySlowFade}"/>
</s:Application>

The executing SWF file for the previous example is shown below:

Delaying effect start

The Effect.startDelay property specifies a value, in milliseconds, that the effect waits once it is triggered before it begins. You can specify an integer value greater than or equal to 0. If you have used the Effect.repeatCount property to specify the number of times to repeat the effect, the startDelay property is applied only to the first time the effect plays, but not to the repeated playing of the effect.

If you set the startDelay property for a Parallel effect, Flex inserts the delay between each effect of the parallel effect.

Repeating effects

All effects support the Effect.repeatCount and Effect.repeatDelay properties that let you configure whether effects repeat, where:

  • repeatCount Specifies the number of times to play the effect. A value of 0 means to play the effect indefinitely until stopped by a call to the end() method. The default value is 1. For a repeated effect, the duration property specifies the duration of a single instance of the effect. Therefore, if an effect has a duration property set to 2000, and a repeatCount property set to 3, then the effect takes a total of 6000 ms (6 seconds) to play.

  • repeatDelay Specifies the amount of time, in milliseconds, to pause before repeating the effect. The default value is 0.

  • repeatBehavior (Spark effects only) Specifies RepeatBehavior.LOOP (default) to repeat the effect each time, or RepeatBehavior.REVERSE to reverse direction of the effect on each iteration.

For example, the following example repeats the Rotate effect until the user clicks a Button control:

<?xml version="1.0"?>
<!-- behaviors\RepeatEff.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">
    <s:layout>
        <s:VerticalLayout/>
    </s:layout>
 
    <fx:Declarations>
        <s:Rotate id="myRotate" 
            angleBy="360"
            repeatCount="0"
            target="{myImage}"/> 
    </fx:Declarations>

    <s:Label text="Click the image to start rotation."/>
    <s:Button id="myButton" 
        label="Stop Rotation" 
        click="myRotate.end();"/> 

    <s:Image id="myImage"
        source="@Embed(source='assets/logo.jpg')" 
        mouseDown="myRotate.end(); myRotate.play();"/>
</s:Application>

The executing SWF file for the previous example is shown below:

All effects dispatch an effectEnd event when the effect completes. If you repeat the effect, the effect dispatches the effectEnd event after the final repetition.

If the effect is a tween effect, such as a MX Fade or MX Move effect, the effect dispatches both the tweenEnd effect and the endEffect when the effect completes. If you configure the tween effect to repeat, the tweenEnd effect occurs at the end of every repetition of the effect, and the endEffect event occurs after the final repetition.

Handling effect events

Every Spark and MX effect class supports the following events:

  • effectStart Dispatched when the effect starts playing. The type property of the event object for this event is set to EffectEvent.EFFECT_START.

  • effectEnd Dispatched after the effect ends, either when the effect finishes playing or when the effect has been interrupted by a call to the end() method. The type property of the event object for this event is set to EffectEvent.EFFECT_END.

  • effectStop Dispatched after the effect stops by a call to the stop() method. The type property of the event object for this event is set to EffectEvent.EFFECT_STOP.

The event object passed to the event listener for these events is of type EffectEvent.

The previous list of events are dispatched by all effects. The Spark and MX effects dispatch additional events. For more information, see Handling Spark effect events and Handling MX effect events.

Flex dispatches one event for each target of an effect. Therefore, if you define a single target for an effect, Flex dispatches a single effectStart event, and a single effectEnd event. If you define three targets for an effect, Flex dispatches three effectStart events, and three effectEnd events.

The EffectEvent class is a subclass of the Event class, and contains all of the properties inherited from Event, including target, and type, and defines a new property named effectInstance, where:

target
Contains a reference to the Effect object that dispatched the event. This is the factory class of the effect.

type
Either EffectEvent.EFFECT_END or EffectEvent.EFFECT_START, depending on the event.

effectInstance
Contains a reference to the EffectInstance object. This is the object defined by the instance class for the effect. Flex creates one object of the instance class for each target of the effect. You access the target component of the effect using the effectInstance.target property.

The following example defines an event listener for the endEffect event:

<?xml version="1.0"?>
<!-- behaviors\EventEffects2.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">
    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

    <fx:Script>
        <![CDATA[
    
            import mx.effects.*;
            import mx.events.EffectEvent;
            import mx.core.UIComponent;
    
            private function endEffectListener(eventObj:EffectEvent):void {
                // Access the effect object.
                var effectObj:Effect = Effect(eventObj.target);

                // Access the target component of the effect.
                var effectTarget:UIComponent = 
                    UIComponent(eventObj.effectInstance.target); 

                // Write the target id and event type to the TextArea control.            
                myTA.text = effectTarget.id;
                myTA.text = myTA.text + " " + eventObj.type;
            } 
        ]]>
    </fx:Script>
    
    <fx:Declarations>
        <s:Fade id="slowFade" 
            duration="2000" 
            effectEnd="endEffectListener(event);"
            target="{myButton1}"/>
    </fx:Declarations>

    <s:Button id="myButton1" 
        label="Button 1" 
        creationCompleteEffect="{slowFade}"/>

    <s:TextArea id="myTA" />
</s:Application>

The executing SWF file for the previous example is shown below:

If the effect has multiple targets, Flex dispatches an effectStart event and effectEnd event once per target, as the following example shows:

<?xml version="1.0"?>
<!-- behaviors\EventEffects.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">
    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

    <fx:Script>
        <![CDATA[
    
            import mx.effects.*;
            import mx.events.EffectEvent;
            import mx.core.UIComponent;
    
            private function endSlowFadeEffectListener(eventObj:EffectEvent):void  
            {
                // Access the effect object.
                var effectObj:Effect = Effect(eventObj.target);

                // Access the target component of the effect.
                var effectTarget:UIComponent = 
                    UIComponent(eventObj.effectInstance.target); 
            
                myTA.text = myTA.text + effectTarget.id + ' : ';
                myTA.text = myTA.text + " " + eventObj.type + '\n';
            } 
        ]]>
    </fx:Script>

    <fx:Declarations>
        <s:Fade id="slowFade" 
            duration="2000" 
            effectEnd="endSlowFadeEffectListener(event);"
            targets="{[myButton1, myButton2, myButton3, myButton4]}"/>
    </fx:Declarations>
   
    <s:Button id="myButton1" 
        label="Button 1" 
        creationCompleteEffect="{slowFade}"/>
    <s:Button id="myButton2" 
        label="Button 2" 
        creationCompleteEffect="{slowFade}"/>
    <s:Button id="myButton3" 
        label="Button 3" 
        creationCompleteEffect="{slowFade}"/>
    <s:Button id="myButton4" 
        label="Button 4" 
        creationCompleteEffect="{slowFade}"/>
    
    <s:TextArea id="myTA" height="125" width="250"/>
</s:Application>

The executing SWF file for the previous example is shown below:

Flex dispatches an effectEnd event once per target; therefore, the endSlowFadeEffectListener() event listener is invoked four times, once per Button control.

Creating composite effects

Flex supports two ways to combine, or composite, effects:

Parallel
The effects play at the same time. If you play effects in parallel, you must make sure that the effects do not modify the same property of the target. If two effects modify the same property, the effects conflict with each other and the results of the effects are undefined.

Sequence
One effect must complete before the next effect starts.

To define a Parallel or Sequence effect, you use the <mx:Parallel> or <,x:Sequence> tag. The following example defines the Parallel effect, fadeResizeShow, which combines the Spark Fade and Resize effects in parallel, and fadeResizeHide, which combines the Fade and Resize effects in sequence:

<?xml version="1.0"?>
<!-- behaviors\CompositeEffects.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">
    <s:layout>
        <s:VerticalLayout/>
    </s:layout>
    
    <fx:Declarations>
        <s:Sequence id="fadeResizeHide"
            target="{aTextArea}"
            duration="1000">
            <s:Fade id="fadeHide" 
                alphaFrom="1.0"
                alphaTo="0.0"/>
            <s:Resize id="resizeHide" 
                widthTo="0" 
                heightTo="0"/>
        </s:Sequence>        

        <s:Parallel id="fadeResizeShow"
            target="{aTextArea}"
            duration="1000">
            <s:Resize id="resizeShow" 
                widthTo="100" 
                heightTo="50"/>
            <s:Fade id="fadeShow" 
                alphaFrom="0.0"
                alphaTo="1.0"/>
        </s:Parallel>
    </fx:Declarations>

    <s:TextArea id="aTextArea" 
        width="100" height="50" 
        text="Hello world."/>

    <s:Button id="myButton2" 
        label="Hide!"
        click="fadeResizeHide.end();fadeResizeHide.play();"/>
    <s:Button id="myButton1"
        label="Show!" 
        click="fadeResizeShow.end();fadeResizeShow.play();"/>
</s:Application>

The executing SWF file for the previous example is shown below:

The button controls alternates making the TextArea control visible and invisible. When the TextArea control becomes invisible, it uses the fadeResizeHide effect as its hide effect, and when it becomes invisible, it uses the fadeResizeShow effect.

As a modification to this example, you could disable the Show button when the TextArea control is visible, and disable the Hide button when the TextArea control is invisible, as the following example shows:

<?xml version="1.0"?>
<!-- behaviors\CompositeEffectsEnable.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">
    <s:layout>
        <s:VerticalLayout/>
    </s:layout>
    
    <fx:Script>
        <![CDATA[
            private function showHandler():void {
                myButton2.enabled=true;
                myButton1.enabled=false;
            }

            private function hideHandler():void {
                myButton2.enabled=false;
                myButton1.enabled=true;
            }
        ]]>
    </fx:Script>
    
    <fx:Declarations>
        <s:Sequence id="fadeResizeHide"
            target="{aTextArea}"
            duration="1000"
            effectEnd="hideHandler();">
            <s:Fade id="fadeHide" 
                alphaFrom="1.0"
                alphaTo="0.0"/>
            <s:Resize id="resizeHide" 
                widthTo="0" 
                heightTo="0"/>
        </s:Sequence>        

        <s:Parallel id="fadeResizeShow"
            target="{aTextArea}"
            duration="1000"
            effectEnd="showHandler();">
            <s:Resize id="resizeShow" 
                widthTo="100" 
                heightTo="50"/>
            <s:Fade id="fadeShow" 
                alphaFrom="0.0"
                alphaTo="1.0"/>
        </s:Parallel>
    </fx:Declarations>

    <s:TextArea id="aTextArea" 
        width="100" height="50" 
        text="Hello world."/>

    <s:Button id="myButton2" 
        label="Hide!"
        click="fadeResizeHide.end();fadeResizeHide.play();"/>
    <s:Button id="myButton1"
        label="Show!" 
        enabled="false"
        click="fadeResizeShow.end();fadeResizeShow.play();"/>
</s:Application>

The executing SWF file for the previous example is shown below:

In this example, the Show button is initially disabled. Event handlers for the effectEnd event toggle the enable property for the two button based on the effect that played.

You can nest <Parallel> and <Sequence> tags inside each other. For example, two effects can run in parallel, followed by a third effect running in sequence.

In a Parallel or Sequence effect, the duration property sets the duration of each effect. For example, if the a Sequence effect has its duration property set to 3000, then each effect in the Sequence will take 3000 ms to play.

Using embedded fonts with effects

The fade and rotate effects only work with components that support the Flash Text Engine (FTE), or with components that use an embedded font. All Spark components, and some MX components, support the FTE. Therefore, the fade and rotate effects work with text in the components.

However, if you apply a fade and rotate effects to a MX component that uses a system font, nothing happens to the text in the component. You either have to embed a font, or use the appropriate Spark component instead of the MX component.

When you apply an MX Zoom effect to text rendered using a system font, Flex scales the text between whole point sizes. While you do not have to use embedded fonts when you apply a Zoom effect to text, the Zoom will appear smoother when you apply it to embedded fonts.

The following example rotates text area controls. The first text area control is defined using the Spark TextArea component, whish supports the FTE. Therefore the text rotates when you apply the Spark Rotate effect to it.

The second text area control is defined using the MX TextArea control. This TextArea control uses an embedded font and, therefore, the text rotates.

The third text area control uses the MX TextArea control with the default system font. Therefore, when you apply the Spark Rotate effect, the text disappears and reappears when you rotate the component back to its initial state:

<?xml version="1.0"?>
<!-- behaviors\EmbedFont.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark"
    width="650">
    <s:layout>
        <s:HorizontalLayout/>
    </s:layout>

    <fx:Style>
        @namespace s "library://ns.adobe.com/flex/spark";
        @namespace mx "library://ns.adobe.com/flex/mx";
        @font-face {
            src:url("../assets/MyriadWebPro.ttf");
            font-family: myMyriadWebPro;
            embedAsCFF: true;
        }

        @font-face {
            src:url("../assets/MyriadWebPro.ttf");
            font-family: myMyriadWebProMX;
            embedAsCFF: false;
        }
</fx:Style>

    <fx:Declarations>
        <s:Rotate id="rotateForward" 
            angleFrom="0" angleTo="45"/>
        <s:Rotate id="rotateBack" 
            angleFrom="45" angleTo="0"/>
    </fx:Declarations>

    <s:VGroup>
        <s:Button label="Rotate Forward"
            click="rotateForward.end();rotateForward.play([l1]);"/>
        <s:Button label="Rotate Backward"
            click="rotateBack.end();rotateBack.play([l1]);"/>
        <s:TextArea id="l1" height="75"
            fontFamily="myMyriadWebPro" 
            text="FTE supported. This text will rotate."/>
    </s:VGroup>

    <s:VGroup>
        <s:Button label="Rotate Forward"
            click="rotateForward.end();rotateForward.play([l2]);"/>
        <s:Button label="Rotate Backward"
            click="rotateBack.end();rotateBack.play([l2]);"/>
        <mx:TextArea id="l2" height="75"
            fontFamily="myMyriadWebProMX" 
            text="Embedded font. This text will rotate."/>
    </s:VGroup>

    <s:VGroup>
        <s:Button label="Rotate Forward"
            click="rotateForward.end();rotateForward.play([l3]);"/>
        <s:Button label="Rotate Backward"
            click="rotateBack.end();rotateBack.play([l3]);"/>
        <mx:TextArea id="l3" height="75"
            text="System font. This text will not rotate."/>    
    </s:VGroup>
</s:Application>

The executing SWF file for the previous example is shown below:

Notice that you had to embed the font twice: once for the Spark TextArea control and one for the MX TextArea control. For more information on embedding fonts for MX components, see Embedding fonts with MX components.

Suspending background processing

To improve the performance of effects, you can disable background processing in your application for the duration of the effect by setting the Effect.suspendBackgroundProcessing property to true. The background processing that is blocked includes component measurement and layout, and responses to data services for the duration of the effect.

The default value of the suspendBackgroundProcessing property is false. You can set it to true in most cases. However, you should set it to false if either of the following conditions is true for your application:

  • User input may arrive while the effect is playing, and the application must respond to the user input before the effect finishes playing.

  • A response may arrive from the server while the effect is playing, and the application must process the response while the effect is still playing.

Disabling container layout for effects

By default, Flex updates the layout of a container’s children when a new child is added to it, when a child is removed from it, when a child is resized, and when a child is moved. Because some effects, such as the move and resize effects, modify a child’s position or size, they cause the container to update its layout.

However, when the container updates its layout, it can actually reverse the results of the effect. For example, you use a move effect to reposition a container child. At some time later, you change the size of another container child, which forces the container to update its layout. This layout update can cause the child that moved to be returned to its original position.

To prevent Flex from performing layout updates, you can set the autoLayout property of a container to false. Its default value is true, which configures Flex so that it always updates layouts. You always set the autoLayout property on the parent container of the component that uses the effect. For example, if you want to control the layout of a child of a Grid container, you set the autoLayout property for the parent GridItem container of the child, not for the Grid container.

You set the autoLayout property to false when you use a move effect in parallel with a resize or zoom effect. You must do this because the resize or zoom effect can cause an update to the container’s layout, which can return the child to its original location.

When you use the Zoom effect on its own, you can set the autoLayout property to false, or you may leave it with its default value of true. For example, if you use a Zoom effect with the autoLayout property set to true, as the child grows or shrinks, Flex automatically updates the layout of the container to reposition its children based on the new size of the child. If you use a Zoom effect with the autoLayout property set to false, the child resizes around its center point, and the remaining children do not change position.

The container in the following example uses the default vertical alignment of top and the default horizontal alignment of left. If you apply a Zoom effect to the image, the container resizes to hold the image, and the image remains aligned with the upper-left corner of the container:

<s:SkinnableContainer> 
    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout> 
    <s:Image source="myImage.jpg"/> 
</s:SkinnableContainer>

In the next example, the image is centered in the container. If you apply a Zoom effect to the image, as it resizes, it remains centered in the container.

<s:SkinnableContainer> 
    <s:layout> 
        <s:VerticalLayout horizontalAlign="center"/> 
    </s:layout> 
    <s:Image source="myImage.jpg"/> 
</s:SkinnableContainer>

By default, the size of the container is big enough to hold the image at it original size. If you disable layout updates, and use the Zoom effect to enlarge the image, or use a move effect to reposition the image, the image might extend past the boundaries of the container, as the following example shows:

<s:SkinnableContainer autoLayout="false"> 
    <s:layout> 
        <s:VerticalLayout horizontalAlign="center"/> 
    </s:layout> 
    <s:Image source="myImage.jpg"/> 
</s:SkinnableContainer>

For a Spark container, if you set the autoLayout property to false, the container does not resize as the image resizes. The image can grow to a size so that it extends beyond the boundaries of the container. You can then decide to wrap the container in the Scroller component to add scroll bars rather than allowing the Image to extend past the container boundaries.

For an MX container, if you set the autoLayout property to false, the container does not resize as the image resizes. If the image grows to a size larger than the boundaries of the container, the container adds scroll bars and clips the image at its boundaries.

Setting UIComponent.cachePolicy on the effect target

An effect can use the bitmap caching feature in Adobe® Flash® Player to speed up animations. An effect typically uses bitmap caching when the target component’s drawing does not change while the effect is playing.

For example, the Fade effect works by modifying the alpha property of the target component. Changing the alpha property does not change the way the target component is drawn on the screen. Therefore, caching the target component as a bitmap can speed up the performance of the effect. The Move effect modifies the x and y properties of the target component. Modifying the values of these properties does not alter the way the target component is drawn, so it can take advantage of bitmap caching.

Not all effects can use bitmap caching. Effects such as Zoom, resize, and the wipe effects modify the target component in a way that alters the way it is drawn on the screen. The Zoom effect modifies the scale properties of the component, which changes its size. Caching the target component as a bitmap for such an effect would be counterproductive because the bitmap changes continuously while the effect plays.

The UIComponent.cachePolicy property controls the caching operation of a component during an effect. The cachePolicy property can have the following values:

CachePolicy.ON
Specifies that the effect target is always cached.

CachePolicy.OFF
Specifies that the effect target is never cached.

CachePolicy.AUTO
Specifies that Flex determines whether the effect target should be cached. This is the default value.

Flex uses the following rules to set the cacheAsBitmap property:

  • When at least one effect that does not support bitmap caching is playing on a target, set the target's cacheAsBitmap property to false.

  • When one or more effects that supports bitmap caching are playing on a target, set the target's cacheAsBitmap property to true.

    Typically, you leave the cachePolicy property with its default value of CachePolicy.AUTO. However, you might want to set the property to CachePolicy.OFF because bitmap caching is interfering with your user interface, or because you know something about your application’s behavior such that disabling bitmap caching will have a beneficial effect on it.