Advertisements
|
||
|
In a previous article, Interactive Spark Components in Flex 4, I showed how to use the new state syntax in Flex 4 to add interactivity to a button. This interactivity added critical feedback to the component, enabling the user to understand, through visual changes in the button's appearance, important changes in state that affected the button's functionality, like hovering over and clicking the button. That version of the button is pretty good—it looks modern and rich, and interacts appropriately as the user interacts with it. But sometimes, you may want enhanced interactivity, not just switching to different states, but instead animating between them.
I discussed animated transitions in a previous article on Artima, State Transitions in Flex 4. Transitions can be used to help the user understand changes in the state of the application and to help them process potentially complicated UIs. Animations can guide the user through changes in the interface, as shown in that previous article's example of the screens of a simple search application. Transitions can also be used at the component level, animating changes in a component's skin state just as they can animate changes in application state. This article will show how easy it is to add these animated transitions to a button's skin.
In the button example from the previous article on component skinning, I added state-specific values to the GradientEntry
objects of the button's fill
to vary the gradient colors and ratios between the up
, over
, and down
states, resulting in this code:
<s:fill> <s:LinearGradient rotation="90"> <s:GradientEntry color="0xf0f0f0" color.over="0xc0c0c0" color.down="0xa0a0a0"/> <s:GradientEntry color="0xffffff" color.over="0xf0f0f0" color.down="0x808080" ratio=".1" ratio.down=".2"/> <s:GradientEntry color="0xaaaaaa" color.over="0x808080" color.down="0xc0c0c0"/> </s:LinearGradient> </s:fill>
For the animated version of the skin, I'll use these same objects, adding only id
elements so that the code can reference the objects that will be animated. I will also add state-specific strength
values to the DropShadow
object, to further enhance the difference between the states (and to show how to enable multiple, different animations in the same transition). These changes result in the following code (differences from the previous version are shown in bold):
<s:DropShadowFilter id="shadow" strength=".3" strength.over=".4" strength.down=".5"/> <s:fill> <s:LinearGradient rotation="90"> <s:GradientEntry id="ge1" color="0xf0f0f0" color.over="0xc0c0c0" color.down="0xa0a0a0"/> <s:GradientEntry id="ge2" color="0xffffff" color.over="0xf0f0f0" color.down="0x808080" ratio=".1" ratio.down=".2"/> <s:GradientEntry id="ge3" color="0xaaaaaa" color.over="0x808080" color.down="0xc0c0c0"/> </s:LinearGradient> </s:fill>
There are different ways to add animation to an application, but the easiest way to animate changes in state values is to use transitions. Flex transitions predate Flex 4, although the animated effects used in transitions were enhanced in the Flex 4 release. Transitions enable developers to create powerful animations by simply declaring which state changes they want to animate, the types of animations desired, and the objects and properties affected by the animation. The rest of the details are handled by the Flex framework: the actual values animated between are derived from the state-specific data of the objects.
For instance, the following example is going to animate the color
property in the GradientEntry
objects in the skin. Since this property knows the values that it will have in the various states, a transition between those states need not specify values for the animation; the Flex transition mechanism will derive them from the state information and populate the animation values appropriately. (In fact, as I discuss in the book, it's better to not hard-code values in the animation, but to let the transition engine determine the properties for you. This approach avoids causing problems when the animation values may not match the values in the states).
To use transitions in a skin (or in any MXML file), you declare a transitions
block, just like the states
block which declares the states used by the skin. Inside the transitions block, you declare a series of Transition
objects for the state changes that you want to animate. Inside of each Transition
object, you then declare the animation effects that you want to run during that state transition. For example, the transitions block for the animated button example looks like this (some parts are commented-out, to be shown later):
<s:transitions> <s:Transition> <!-- animation effects... --> </s:Transition> <s:Transition toState="down"> <!-- animation effects... --> </s:Transition> <s:Transition fromState="down"> <!-- animation effects... --> </s:Transition> </s:transitions>
In this transitions block, we have one default transition (with no specified fromState
or toState
) which will play during any state transition if no other state-specific transition plays. We also have two transitions that will play when the state enters or exits the down
state (for a reason that we'll see later).
The types of animation effects possible in state transitions are infinite, bounded only by the properties that you want to animate during state changes. But in general, transitions consist of effects like Move
and Fade
as objects change position and visibility between states. You can see these effects in use in the transitions article mentioned above.
In this button example, however, we want to animate properties that are not handled by the Move
and Fade
effects; we will be animating the strength
of the drop shadow, the gradient ratio
, and the gradient color
s. For these animations, we will need to use general-purpose Animate
effect and the AnimateColor
effect.
The Animate
effect was created in Flex 4 to handle animating arbitrary properties on objects; you tell it the target object to animate and the properties on that object and it animates between the values specified (or the values picked up from the states, as in the example here). Other effects like Move
and Fade
operate on specific properties of the target object, whereas Animate
can act on any property. Animate
is like the AnimateProperty
effect in Flex 3, although Animate
can handle multiple properties simultaneously, and shares other capabilities of the new Flex 4 effects like arbitrary type interpolation. In fact, Animate
is the superclass of all of the new Flex 4 effects and is the main engine behind these new effects, so any use of one of the new effects will actually be using Animate
behind the scenes. But we will be using the effect directly here as we animate the ratio and strength properties.
We have two target objects to use Animate
on: the DropShadow
and second GradientEntry
(the only one whose ratio changes between states). We therefore use two Animate
effects to run animations on these two target objects:
<s:Animate target="{shadow}"> <s:SimpleMotionPath property="strength"/> </s:Animate> <s:Animate target="{ge2}"> <s:SimpleMotionPath property="ratio"/> </s:Animate>
These effects will animate the strength
property on the shadow
object and the ratio
property on the ge2
object. The start and end values are determined automatically based on the values of those properties in the states being animated between.
To animate the color property of the gradient, we use the AnimateColor
effect. We could also use Animate
to animate the color, but colors require a bit more care to animate (you cannot simply animate colors as numbers, like Animate
does by default; you need to set a type interpolator on the effect to interpolate the color values correctly). AnimateColor
handles the details for us, correctly interpolating RGB colors.
<s:AnimateColor targets="{[ge1, ge2, ge3]}"/>
Note here that this one effect is animating all three gradient entries independently; we just set all three objects as targets of the effect.
The last detail of the animations is that a Transition object encapsulates a single animation effect. But in this case, we want to run all three effects at the same time. We we wrap the effects with a Parallel
effect, which plays the animations simultaneously. Putting it all together, we end up with the following transitions block in the skin:
<s:transitions> <s:Transition> <s:Parallel duration="500"> <s:Animate target="{shadow}"> <s:SimpleMotionPath property="strength"/> </s:Animate> <s:Animate target="{ge2}"> <s:SimpleMotionPath property="ratio"/> </s:Animate> <s:AnimateColor targets="{[ge1, ge2, ge3]}"/> </s:Parallel> </s:Transition> <s:Transition toState="down"> <s:Parallel duration="250"> <s:Animate target="{shadow}"> <s:SimpleMotionPath property="strength"/> </s:Animate> <s:Animate target="{ge2}"> <s:SimpleMotionPath property="ratio"/> </s:Animate> <s:AnimateColor targets="{[ge1, ge2, ge3]}"/> </s:Parallel> </s:Transition> <s:Transition fromState="down"> <s:Parallel duration="250"> <s:Animate target="{shadow}"> <s:SimpleMotionPath property="strength"/> </s:Animate> <s:Animate target="{ge2}"> <s:SimpleMotionPath property="ratio"/> </s:Animate> <s:AnimateColor targets="{[ge1, ge2, ge3]}"/> </s:Parallel> </s:Transition> </s:transitions>
Note that the only difference between the three transitions is the duration
assigned to the effects; we use a duration of 500 for the default transition (which will take place when the mouse moves over and out of the button area) and 250 for the other transitions. This difference is important because the action of clicking on the button should generally be much quicker than a more transitional animation like moving the mouse over the button. When the user clicks the button, you want to action to occur very quickly, and not to make them wait for an animation to occur, which can make the application appear sluggish. Pretty, but sluggish.
In fact, durations of 500 and 250 milliseconds are far too long for both of these animations. I only made them that long to make the animations obvious when playing with the demo in this article. The click animation should be very quick, like 50 ms. In fact, skipping an animation on an atomic action like clicking is the best approach in many cases. But if you do add an animation to it, make it quick. The other animation can be longer, but more like 200 ms than the current 500 ms; long enough to animate the change, but not so long that the user feels that it's sluggish.
Run the demo application below. By default, the button uses the Stateful skin. When you hover over and click on the button, notice the sudden changes in the button's visual appearance. Now select the Animated skin from the drop down list. Notice that the mouse interactions now trigger animations between those visual states.
To view this page ensure that Adobe Flash Player version 10.0.0 or greater is installed.
Either scripts and active content are not permitted to run or Adobe Flash Player version 10.0.0 or greater is not installed.
As you can see from the demo application, it is easy to add animations to your component skins, building on the states capabilities of Flex to animate changes in state. All I did to take the previous button example to an animated version was to add reference id
s and a transitions
block to declare the animations to use (plus a change in the DropShadow
's strength property just to add more to the overall effect).
The source code for this application and its two skins can be found here. For more information on the topics covered in this article, check out the previous articles on transitions and component skinning, plus the following Flex 4 Fun chapters: States, Transitions, and Skinning Components, and several chapters on Flex 4 effects.
Chet Haase is author of Flex 4 Fun, which is available as a PrePrint™ (early access release) at: http://www.artima.com/shop/flex_4_fun |
Adobe's Flash Builder 4
http://www.adobe.com/products/flashbuilder
Flex SDK 4
http://opensource.adobe.com/wiki/display/flexsdk/Flex+SDK
Chet's article "Interactive Spark Components in Flex 4" is at:
http://www.artima.com/articles/interactive_spark_components_in_flex.html
Chet's article "State Transitions in Flex 4" is at:
http://www.artima.com/articles/state_transitions_in_flex_4.html
For more on states in Flex 4, see "Working with States in Flex 4":
http://www.artima.com/articles/flex_4_states.html
Flex.org
http://www.flex.org
Have an opinion? Be the first to post a comment about this article.
Chet Haase worked as a senior computer scientist on the Flex SDK team at Adobe Systems, Inc., during the Flex 4 release. He was responsible for Flex effects, and writing the next effects infrastructure and classes for Flex 4. Prior to his work at Adobe, he worked at Sun Microsystems for several years, and co-authored the book Filthy Rich Clients about creating rich user experiences with the Java client platform. His entire career has been in graphics software, from the application level to APIs and libraries to drivers for graphics chips. As long as it puts pixels on the screen, he's interested. He earned a B.A. in Mathematics from Carleton College and an M.S. in Computer and Information Sciences from the University of Oregon.
Chet posts regularly to his technical blog at http://graphics-geek.blogspot.com, where you can find articles, videos, demos, and plenty of source code. Chet is also interested in writing and performing comedy; you can see some his work in this completely unrelated field at http://chetchat.blogspot.com, and in his book When I am King..., which is available at Amazon.com.
Artima provides consulting and training services to help you make the most of Scala, reactive
and functional programming, enterprise systems, big data, and testing.