Showing posts with label actionscript. Show all posts
Showing posts with label actionscript. Show all posts

Tuesday, October 20, 2009

Video: Flex 3 Easing with Flex 4 Effects

Flex 3 Easing with Flex 4 Effects, the next episode in the gripping and suspenseful series CodeDependent, is now available from Adobe TV.

This show is basically a recap of an earlier blog article I wrote, Penner for your Thoughts (named for the author of the Flex 3 easing functions, Robert Penner), except this time it's in video form (for the reading-impaired). The topic is about using the old easing functions in Flex 3 through the new IEaser interface that the Flex 4 effects require. See the article for more details about the whys and hows of this rather neat hack.

Meanwhile, here's the video:

Here is the demo application:

And here is the source code. Be sure to check out the blog article for more details on how the code works.

Finally, here's where you can find the CodeDependent videos on iTunes.

Enjoy.

Friday, August 28, 2009

Scoping Strategies

I just fixed a lurking bug in my code today that was related to ActionScript's scoping rules. The bug wasn't obvious to me when I first wrote it, and took some head-scratching when I fixed it. So I thought I'd post in in case this behavior isn't obvious to anyone else eading this (say, coming from a Java background like I do, where this behavior doesn't exist).

I'll boil it down to a simpler 'puzzler' question:

What do you think this prints out?

            var i:int;
           for (i = 0; i < 2; ++i)
           {
               var blah:Object;
               trace("blah = " + blah);
               blah = i;
           }

Or how about this?

            for (i = 0; i < 2; ++i)
           {
               var blarg:Object = null;
               trace("blarg = " + blarg);
               blarg = i;
           }

(I'll put the answer at the end of this post, so that I don't blow the surprise for anyone wanting to figure it out before proceeding.)

What's going on here is that the scope of these variables (like all variables in ActionScript) is at the level of the function. That's right: even though the variable is declared inside the for() loop, they are scoped to the overall function. There are various implications and consequences that come from this scoping rule, but the specific one we're dealing with here is that that scope is also the place where the variable receives its implicit assignment. So in the case of the first example above, blah is assigned the default value of null just once. When we come around to the variable declaration again, it does not get a second implicit assignment, because it's as if the variable were declared at the top of the function, since that's its scope.

Meanwhile, in the second example, blarg is given an explicit assignment. This means that every time around our for() loop, we assign the value of null to blarg, so that the variable is always initialized to that value at the point where we declare it in the code.

To my Java developer eye, these looked equivalent: an implicit assignment would happen at the same time as an explicit assignment. But now I realize that if you really want a variable to have a specific default value, assign it explicitly or suffer the possible consequences.

Moral of the Story: Always assign a default value to a variable, especially iuf the variable is declared in a loop where you expect it to have some default value.

Addendum: To test this behavior in Java, I tried to write similar code to see the results. It turns out that the code wouldn't even compile; accessing the variable (even to System.out.println() it ) without declaring an initial value for it threw a compiler error. I could swear this type of code used to work, but perhaps they tightened up their variable declaration policy since I used that approach.

Answers:

The first example prints out:

    blah = null

   blah = 0

and the second example prints out:

    blarg = null

   blarg = null

Monday, June 8, 2009

Video: Easing Does It

Easing Does It, the next episode in the gripping and suspenseful series CodeDependent, is now available from Adobe TV.

This show is a continuation of the episode A Moving Comparison, in which we saw how to create simple animations in Flex 3 and Flex 4. This time, we'll see how to add 'easing' behavior to our Flex 3 animation to create non-linear motion.

Here's the video:

Here is the demo application:

And here is the source code.

Enjoy.

Friday, May 22, 2009

Video: CodeDependent #2, er, 7

Now things are really moving...

The next episode of CodeDependent, "A Moving Comparison," is out. There are actually 7 episodes in the show so far, but 5 of those are reruns, rendered onto the spiffy new CodeDependent set. (I suspect that the earlier versions of those episodes, rendered on the standard Aodbe Developer Connection backdrop, will become collectors' items. Somewhere. Sometime. Perhaps they will be re-master and re-released someday, as "Codedependent Classics").

This latest show is a brand new one, starting right where the first one, "Graphics in Flex 3 and Gumbo", left off. In the first episode, I compared simple custom graphics in Flex 3 to simple graphics in Flex 4 (codename Gumbo). In this episode, I compare simple animations in Flex 3 and Gumbo on those same graphics objects.

Here's the video:

Here are the demos:

And here is the source code.

Enjoy.

Monday, May 11, 2009

Video: CodeDependent #1

Adobe TV has just posted the first in what I hope to be a very long run of my new show, “CodeDependent”. Fortunately, the show is not on the Fox network, so that may give it a better chance of not being canceled.

The CodeDependent show is not that different from the videos I’ve been doing already: short tutorials on various aspects of Flex and Flash that I find interesting. The biggest change is that they should be more regular (we’re aiming for an every-other-week schedule as we settle into it). Also, they producers gave me a nifty new grayscale CG set design to match my nifty old grayscale CG personality.

This first show is a simple tutorial on Flex 3 and Flex 4 (codename Gumbo) graphics. For the Flex 3 demo, you'll see how to drop down into ActionScript code to draw simple graphics through the Flash APIs into your Flex application. For the Flex 4 version, you'll see you to do the same thing through MXML graphics tags. In future episodes, we'll build on these simple examples and see how to animate the objectsand how to get more realistic animations. (Can you feel the suspense of this cliff-hanger? I’m trying to incorporate standard television series techniques into the show. Look for a laughtrack soon.) But I’m getting way ahead of myself.

Here’s the video:

Here’s the awesome demo application:

And here’s the source code.

Enjoy. And welcome to my show…

Tuesday, March 24, 2009

Video: A Moment of Reflexion

Finally, after great suspense and bitings of nails, Adobe TV has posted my Reflexion Container video. This video was meant to be Part 1 in a sequence of 2 parts, but for reasons that escape me, Part 2 (What a Drag) got posted first. Many things in life are beyond our control: the weather, the things our children say in public, and our cravings for bacon. Apparently, the order of videos posted on Adobe TV is just another random factor in life.

This video shows a container that displays an image along with its reflection. The application has sliders to control the various parameters of the reflection, so that you can see how these parameters affect the realism of the reflection. The reflected image can be changed by clicking on a different thumbnail or, as we saw in the previous Drag and Drop video, by dragging and dropping that thumbnail onto the reflection container.

The techniques used in creating the reflection are not new; I wanted to create this demo to show how they might be used in a sample application container. Also, I wanted to expose the controls to the reflection parameters so that we could see how the various mechanisms affect the result. A couple of resources that I consulted for the reflection technique include the ReflectionPanel demo by Romain Guy (also the photographer of the pictures used in the demo) in a Java book that I've read entitled Filthy Rich Clients and, a bit closer to Flex, an article by Ben Pritchard on the Adobe Devleoper Connection site..

Video being what it is, you may not be able to see some of the impact of the reflection parameters that clearly. For example, when I talk about blurring the reflection to make it more realistic, it actually looks kind of blurry to begin with. Here is the demo itself so that you can play with it directly:

And here is the source code for anyone wishing to see how it actually works. I should point out that it's not the cleanest code, since it was written in a conference rush. The reflection code is the main point of it all, and it's pretty striaghtforward, but the mechanisms of updating the image and recreating the reflection sprite could definitely be cleaner. But in the interests of getting the code out there for people to see, I'm posting it earlier than I might otherwise.

Here's the video - enjoy:

Tuesday, March 17, 2009

Animation Spawning

A developer posted an issue on one of the Flex forums last week that the new Gumbo effects had choppy artifacts when running his test case, especially when compared to similar code that used the Tweener animation library. Being of a sensitive and insecure nature, and wanting to fix any bugs in my effects code, I looked into the problem and discovered some things about animation seemed worth this post.

The Test Case

The original test case used a 3D rotation effect. But between different behavior between Tweener and our FxRotate3D effect and my workspace being a tad torn apart at the moment, I simplified the case down to animating a small square to the current mouse position. Specifically, as you move the mouse around you set a new position to which the the square will animate. If the mouse stops moving, the square will animate toward that position and stop when it gets there. Otherwise, the square will keep animating toward whatever the new position is, changing direction a sthe mouse moves around.

The original test case was set up to start a new animation every time the mouse moved, in a mouse movement handler. Here's that code for the Tweener version:

       private function mouseMoveHandler(event:MouseEvent):void
       {
           Tweener.addTween(rect,
               {x:event.stageX,y:event.stageY,time:2});
       }

where this call animates the rectangle's x and y properties from their current values to the new x/y location of the mouse over a duration of 2 seconds.

Here is similar code for the Flex effects version:

       private function mouseMoveHandler(event:MouseEvent):void
       {
           mover.xTo = event.stageX;
           mover.yTo = event.stageY;
           mover.stop();
           mover.play();
       }

where the Flex mover effect is declared like this:

    <Declarations>
       <easing:Exponential id="exponentialEase" easeInFraction="0"/>
       <FxMove id="mover" target="{rect}" easer="{exponentialEase}" duration="2000"
           animationUpdate="updateHandler(event)"/>
   </Declarations>

Note that the Exponential ease is not in the SDK yet - I created one for this example to mimic the behavior of Tweener's default easing. I will be adding that class sometime soon, along with more of the old easing classes for the Flex3 effects.

The Demos

Here's the Tweener version of the application. If you move the mouse constantly in a particular direction, you can see the square hopping to keep up with it. It's not smooth, but it does aggressively try to keep up, and gets smoother when the mouse stops:

And here's the Flex effects version of the application:

Note that the square seems to move much more slowly when the mouse is in constant motion. In fact, inside of browsers on the Mac (which was the test platform for the person that submitted the original issue), sometimes the square doesn't move at all until the mouse stops moving, at which point the animation engine kicks in and we get a smooth animation of the square.

Now notice that the Flex effects test has a checkbox in the upper-right, cunningly labeled "Smooth Moves." If you check that, you may notice that the animations are a bit snappier, and closer to what you are seeing in the Tweener version. (In fact, I see smoother performance in general with this version than the Tweener version, probably because we force a higher frame rate on animations by posting an updateAfterEvent request whenever there is a Timer event, which will force a render event between the usual enterFrame events). And on the Mac, you should notice that you no longer get complete freezing or jarring delays while the mouse is moving around. All in all, the app is much better behaved when that box is checked.

So what was the fix?

The Fix

It turns out that the original method of spawning new animations for every mouse move is not just more overhead than you really want or need in your animation - it's actually bad practice. Depending on the platform you're on, the frame rate you're getting, the event at which Timer events (which are currently the basis for the Flex effects animation updates) are coming in, and the rate at which mouse events are coming in, you're going to get somewhat unpredictable behavior. What's happening is this:

Between actual animation updates, whether they happen because of a Timer (in the case of Flex effects) or the enterFrame event (in the case of Tweener), you may be restarting your animation one or more times. And depending on when those restarts happen relative to the next animation update, the behavior of those animations may not be what you want. In the case of Flex effects, imagine that you restart your animation 4 times between animation updates because mouse move events came in that many times between updates. When the system finally gets to update the animation, it will use the last one started, which may have started just prior to, or even at the same time as, the current update time. So you may get no movement whatsoever from your animation because according to the time elapsed between the time that you started it and the time you measured it, no time has passed, so the object shouldn't move. Then you start getting mouse events again, and spawning new animations, and you eventually reach the next animation update event only to find that, once again, you are processing an animation that hasn't had any time pass since it was begun.

"But, but, but, " you may justifiably be stuttering, "What about Tweener? Why is that system able to handle this situation better and keep that object moving?"

Why, indeed? The answer is that it does not actually record the true start time for any animation, but rather uses the time used at the last animation update, which is the previous enterFrame event. So when you restart an animation just prior to the next enterFrame event, it doesn't matter that very little or no real time passes between starting it and processing it the first time - the system will process it as if it had been started at the previous enterFrame time. So our little square is able to keep moving around on the screen because the constantly restarted animations are using inflated elapsed times for every calculation.

Note: I'm not saying that Tweener should or should not do it this way; it's just the way that that system happens to work, just as Flex effects work differently by assigning a real start time based on when the effect is started.

But when I realized that that was the key that was causing the stutter I was seeing on Mac browsers for the Flex effects version, I realized that the problem was not in the way that we were handling animations (because I do want Flex effects to reflect the real elapsed time, regardless of when they are started), but rather in how and when these animations were being launched. In particular, it doesn't make sense to launch several animations in between times when we're actually updating the animation. Instead, it makes more sense, both because of the issues here and from the "don't do so freaking much work" standpoint, to track the mouse movement but only cause it to restart animations at other, less frequent intervals.

The "fix" embedded in the "Smooth Moves" variation in the application above does just that: it tracks the mouse movement constantly and then uses the last known position to launch a new animation in the next enterFrame handler (if the position has changed since we started the last animation). In this way, we can be assured that we're letting our animation run at least a little bit before we clobber and restart it with new values, potentially stalling out because we're not allowing things to move at all before we restart a new animation in place of the older one.

Here's the complete code for the Flex effects version - you can see how we handle the animation-spawning logic differently based on the setting of the checkbox. By default, we restart the effect every time the mouse moves. But when the checkbox is selected (smoothMoves.selected == true), then we only record the last mouse position in mouseMoveHandler(), and we defer spawning a new animation until the next enterFrame() call.

<?xml version="1.0" encoding="utf-8"?>
<FxApplication xmlns="http://ns.adobe.com/mxml/2009" width="100%" height="100%"
   enterFrame="enterFrame(event)" mouseMove="mouseMoveHandler(event)"
   xmlns:easing="easing.*">
   <Script>
       <![CDATA[
       import mx.events.AnimationEvent;
      
       private var lastMouseX:int;
       private var lastMouseY:int;
       private var mouseMoved:Boolean;
      
       private function mouseMoveHandler(event:MouseEvent):void
       {
           if (smoothMoves.selected)
           {
               lastMouseX = event.stageX;
               lastMouseY = event.stageY;
               mouseMoved = true;
               if (!mover.isPlaying)
                   mover.play();
           }
           else
           {
               mover.xTo = event.stageX;
               mover.yTo = event.stageY;
               mover.stop();
               mover.play();
           }
       }
       private function enterFrame(event:Event):void
       {
           if (mouseMoved)
           {
               mover.xTo = lastMouseX;
               mover.yTo = lastMouseY;
               mover.stop();
               mover.play();
               mouseMoved = false;
           }
       }
       ]]>
   </Script>
   <Declarations>
       <Power id="powerEase" easeInFraction="0" exponent="7"/>
       <easing:Exponential id="exponentialEase" easeInFraction="0"/>
       <FxMove id="mover" target="{rect}" easer="{exponentialEase}" duration="2000"/>
   </Declarations>
   <Rect id="rect" width="20" height="20">
       <fill>
           <SolidColor color="0xff0000"/>
       </fill>
   </Rect>
   <HBox top="10" right="10">
       <Label text="Smooth Moves"/>
       <CheckBox id="smoothMoves"/>
   </HBox>
</FxApplication>

So: don't spawn animations too aggressively; you may not get the effect you're after from the effect. And note that this approach should work just as well for Tweener (or any other animation engine) as for Flex effects; Tweener only happened to look better in this situation because of its inherent timing behavior, but there would be no reason not to back off and have it spawn less animations too.

p.s.

As a side note, I should point out that another artifact that the original poster ran into was caused by playing the Flex effect multiple times without stopping the previous one(s). You should always, at least in the current Flex effects system, stop() currently playing effects on the same target/property, because otherwise you're effectively giving that property multiple, conflicting instructions at every animation update, as all of the active animations on that property may try to assign different values to it. Tweener does not have this issue because it auto-stops any animations running on that target/property, but Flex effects require you to stop the effect itself. Note that this doesn't mean that you need to stop all effects in the system when you play a new one, or even all effects running on a particular target; the only time that it's an issue is when there are multiple effects running on the same property of the same target(s), as is the case in the example here, where we are always changing the same target's x and y properties.

If you're interested in the full source code, which includes the simple examples above plus the supporting Exponential and Tweener classes used by the examples, here it is. Note that building the Flex effects example requires some recent build of the Gumbo SDK, as it uses classs that only exist in that version of the platform. If you really want to, you should be able to run similar tests with Flex 3 effects (using components instead of the new Gumbo Rect object), since they use the same underlying Timer facility. But the main point of the article was in the demos and explanations; the code is just provided to give a sense of closure.

Thursday, March 12, 2009

AS34J2: ActionScript for Java Developers, Part Two

The suspense is over, life can return to normal: JavaWorld has posted the second and final installment of my two-part article, ActionScript for Java Developers, which is based on a presentation that James Ward and I did at the Devoxx conference in December.

Part 2 is a bit deeper than Part 1. Now that we've gotten past some of the basic syntax issues in the languages, we're able to get into more complex topics, including Properties, Dynamic aspects of ActionScript, and Functions.

Enjoy...

Tuesday, February 17, 2009

AS34J1

JavaWorld has just published Part 1 of a two part article entitled ActionScript for Java Developers (though I prefer the more unparsable name AS34J). It's based on a presentation that James Ward and I did at the Devoxx conference in December, walking through various aspects of similarity and differences between Java and AS3. The point is not to promote one language or platform over the other, but rather to take a closer look at AS3 with Java-tinted glasses. Enjoy...

Monday, February 9, 2009

Video: Gumbo Effects

Adobe TV has posted a video where I talk about some of the new effects capabilities in the next release of Flex, codenamed 'Gumbo'.

For example, the effects can now animate arbitrary objects and types (not just UIComponents and Numbers), which enables things like the new FxAnimateColor effect. Also, there is a new 'easing function' interface that makes the built-in easing functions more flexible and also 'easier' for custom implementations. And there's new repetition behavior that makes reversing and looping animations simple.

Work is still ongoing: we're adding more functionality to the effects system constantly. In fact, I'd better get back to that now. Meanwhile, check out the video for a preview of where we're headed:

Thursday, January 29, 2009

Video: MAX Presentation on Filthy Rich Flex Clients

Adobe TV has just posted my session Filthy Rich Flex Clients, which was recorded at MAX 2008. It's a screencast with audio, so you get the dual benefits of seeing the slides/demos and not having to watch me deliver them.

It's a pretty dense presentation, in which I cover some Flash platform graphics fundamentals, how effects work in Flex3, how they will work in Gumbo, and (now that I built up the rest of that material) how to do some particular 'Filthy Rich Client' effects in Flex.

Check it out at Adobe TV in larger resolution, or watch it from the comfort of this handy blog post:

In case the text in the video is hard to read, here's the presentation in PDF format for your amusement.

Thursday, January 15, 2009

Video: What a Drag

I think I must be living backwards in time, because the second part of a video I shot in December just became available on Adobe TV (before the first part was released). Perhaps they're just trying to build suspense, but in a Jeopardy way, like telling you the answer and then having you wonder what the fascinating question was.

Actually, the video does stand on its own; it is about 'Dynamic Drag and Drop' behavior in Flex, and is not dependent on the previous part. But it does use an application called Reflexion, which is about creating reflections for Flex display objects, and that's the part that you'll hav eto wait for a while to see. (Ooooh, I can feel the tension building...).

Anyway,please enjoy the video. It's another in a series of demos I've been writing around the general topic of giving the user good visual feedback to enable better user experiences. I hope it's not too much of a drag...

By the way, I have not (you may have noticed) posted the source for this yet. I may wait until the first part of the video, which shows the reflection technique, goes live. Or maybe that's just my petty rationalization for not doing it right now because I'm a tad busy working on Flex beta features. But it will show up here eventually.

Update: the first part of this demo is now available; see this later blog entry for that video. Also, I finally got around to posting the source code and the demo; they're also in that later blog entry. So what are you still reading this for? Go!

Monday, November 10, 2008

Video: Custom Flash Graphics

Adobe TV has posted my final Flex in a Week video. This one is on the use of Flash graphics objects in Flex applications, covering both drawing directly into the Graphics object for custom rendering in your updateDisplayList() method as well as creating and adding Flash shapes to your components. (Note that you have to have a completely cusom component, subclassing UIComponent, in order to add non-component children such as DisplayObjects or Sprites to the child list of your component; other Flex components only understand Flex component children).

It's not terribly advanced, but is meant more as an introduction to some of the graphics basics, including Flash's use of retained mode rendering and why you always need to clear() the graphics display list.

The source code for both examples is available here.

Wednesday, October 22, 2008

Video: Glow For It

Here's another Adobe TV video in the Flex in a Week training series. This one's about using Flash filters in Flex applications. Specifically, I discuss instantiating and animating a Glow filter on a button, but the techniques discussed are applicable to using filters in general. The source code is fairly self-explanatory, but feel free to grab the two files I cover in the video: GlowingButton.mxml and AnimatedGlowingButton.mxml. Glow ahead, check it out!

Wednesday, October 15, 2008

Video Time

Here's another video to watch, on some of the details about using the Flash Timer. I shot this video as a part of a just-posted series for the Flex in a Week training shows. This is the same topic and application that I cover in my earlier Time's Up blog entry, but in video form. It's so much more dramatic this way. And video seems so much more fitting for the material. I'm talking about time, after all, so why not cover the topic using time-based media? It was either this or a song, and I thought I'd save you that torture.

Monday, September 15, 2008

Video: Sorted Details

I shot a video tutorial recently of my Slide Sorter demo (which is also covered in this earlier blog entry), and it just got posted on Adobe TV. Here it is:
To see the running demo in action (which is better than a static picture of the demo, which would be the demo inaction), as well as the source code, see my earlier Sorted Details blog entry.

Tuesday, September 9, 2008

Flexy: A Flexible AS3 Animation Library

I'm currently working on new animation capabilities for the next release of Flex. We have some great stuff in there already, such as the effects infrastructure and state transitions, but I'm rounding out the functionality and rethinking some of the APIs to make the system more powerful and usable by both tools and developers.

For my effects work, I'm mostly concerned about Flex developers because, well, that's what the library is for.

But it occurred to me, through conversations and through random web perusals, that an animation system that could also be used outside of Flex might be interesting to the people doing ActionScript3 applications without the Flex framework, or to people doing both Flex and non-Flex AS3 programming. It also occurred to me that much of my code was Flex-agnostic. Of course, the code that is tied to Flex effects and transitions is necessarily dependent upon Flex, but the core animation engine really doesn't care what it's animating or how; it's simply varying values over time.

So I took a pass over the code to make it truly Flex-less, which involved removing a total of like 5 lines of code from my existing classes. I also added a class called ObjectAnimator, which is a simplified version of the new Flex Animate effect class.

But probably more interesting to the people reading this, I am putting out the results here as something for people to try out.

Caveat: (I love using the word Caveat. For one thing, it's a great hedge. But also, it's the only Latin word I know and surveys show that people who speak Latin are smarter. Except the Romans, when they let their city get overrun and their empire trampled) This is not a released product, either from Adobe or from me. Instead, it's a technology demo that shows you what the new Flex animation system does. My main focus is, and should continue to be, making Flex animation rock, which means that I can't spin up effort supporting an animation library that's a separate entity. Having said that, the code that I'm delivering here is about a 99% (taking a complete guess because I don't want to bother diffing and counting lines of code) copy of the code in Flex, so it's not like this is just some random code project spew.

There are various reasons I'm doing this:

  • Nice guy: This is just another example of what a great guy I am. A real pal. Your source for fun code and good CPU times.
  • Feedback: I'd like to get people, especially animation-savvy developers, interested in what I'm doing for Flex and giving me some feedback on things they think I'm missing, or things they would also like to see, or problems that they are having. I don't want Flex to be a constraint that makes it hard for those people to check out the animation code and play with it.
  • Share the wealth: If the stuff I'm doing for Flex can be useful in other Flash contexts, great! As I said, my main focus needs to be Flex. But if I'm doing generic work that can be used elsewhere in the Flash world, that's okay by me.

Demos are usually good, so here's one:

And here's the source code. The demo was built in Flash authoring (although you should be able to get the same result in either Flex or pure AS3 programming - I just used Flash as a proof-of-concept for this non-Flex animation library). The creation of the ball and button aren't obvious from the code because I did it in the authoring tool, but they aren't the main course of that demo anyway, and it would be easy to write something similar purely in code.

I was about to post this article, but then I realized that maybe you'd be interested in what the animation library actually does. Here are some quick explanations, but feel free to check out the demo code and the ASDocs for more concrete details:

  • Property Animation: Animating one or more properties on a given object for a set duration. This means calculating the in-between values and setting them on the object directly.
  • Arbitrary Type Interpolation: Animation of properties of any type: as long as you supply an IInterpolator implementation to the animation it can figure out how to calculate the in-between values. For example, there is a ColorInterpolator supplied with the library that handles per-channel interpolation for RGB uint values.
  • Easing: There is a simple IEaser interface with several built-in implementations to enable various linear and non-linear time easing calculations, providing for more realistic animations. For example, the Bounce demo above uses a cubic Power ease that accelerates for the full duration down.
  • Repetition. I repeat: Repetition: Animations that automatically repeat, either looping or reversing, for specified numbers of times. For example, the Bounce demo specifies a repeatCount of 2 that reverses each time to get that in-out behavior of both the bounce-down/up and the squish out-in effect.
  • Size Matters: The library is 10k. 10k! That's like less memory than Bill Gates thought anyone would ever want on the PC! Less than the word count of this blog (if I'd repeated each word 10 times)!
  • Multiple Leves of Control: ObjectAnimator exists to make creating animations even easier; you don't have to handle the animation events, but rather just tell it what properties to animation on which object between which values, and ObjectAnimator does the rest. But if you'd like to get your hands dirty, it's not that much more work to create the Animation object directly. Here's source code for an ObjectAnimator-less version of the same demo. Note that the steps to creating the animation are just about the the same as in the other version, but that we also have to set up and handle the update events in order to actually move the target object.

In the future, I may try to integrate this side-project more closely with Flex. For example, it's possible to build parts of the Flex framework (or any Flex project) as a separate library. For now, just to expedite getting this out there, I copied the code and created this project in Flash (that also helped me ensure that there were no Flex dependencies). But stay tuned to see if/when I start using the same source/build base for this project as for the rest of my Flex work.

So take the library. Try it out, with Flex projects and non-Flex projects. Check out the ASDocs. Check out the demo code. Check out the Flex opensource site for the actual code (only ObjectAnimator does not exist in Flex and most of that is culled from the Animate/AnimateInstance classes). Let me know how it works for you and what else you'd like to see in a core animation package.

Oh, and tell your friends what a nice guy I am.

Friday, September 5, 2008

Presentation: Filthy Rich [Flex] Clients

The video for my recent presentation at the 360Flex conference was just posted. Here it is for your viewing pleasure. Grab some popcorn, turn down the lights, and settle back in your chair for this action-packed Flex thriller:

Tuesday, August 5, 2008

SpringItem

Someone asked, in the comments to my Springtime posting, how that effect could be generalized to apply to DataGrid items. I came up with this simple demo to show the same effect at work for each item in the grid:

The only change I needed to make to the underlying Spring effect was to make it deal with IUIComponent, instead of UIComponent. The original demo only works on components. In the case of DataGrid items, however, we have item renderers, which are not UIComponents, but which do implement the IUIComponent interface. So I changed the code in SpringInstance accordingly, modifying UIComponent to IUIComponent and changing a call to componentToGlobal() to localToGlobal() (to get the mouse coordinates in terms of the global location) instead, and voila, it's a beautiful, springy data grid.

I had to make one change to my default DataGrid component to make it look reasonable: I centered the text in the cells with the text-align="center" style attribute. Without this change, it looked like the spring effect was happening off-center, just based on the default position of the text on the left that would then go shooting further to the left as it sprang out. Also, I enabled double-click events and added the spring effect based on double-clicking on an item, grabbing the itemRenderer from the event as the source for the effect.

The abbreviated MXML code for the application is here:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:effects="effects.*" layout="absolute" width="600">
    <effects:Spring id="spring" duration="500"/>
    <mx:DataGrid textAlign="center" width="100%" doubleClickEnabled="true"
        itemDoubleClick="spring.play([event.itemRenderer])">
        <mx:ArrayCollection>
         <mx:Object>
            <mx:Label>Thunderbird</mx:Label>
            <mx:Price>$2.99</mx:Price>
            <mx:Rating>8</mx:Rating>
            <mx:Notes>Hint of cough syrup</mx:Notes>
         </mx:Object>
         <!-- other items omitted for brevity... -->
      </mx:ArrayCollection>
    </mx:DataGrid>
</mx:Application>

The code for the effect itself can be obtained in the zipped source files.

I expect a similar approach could be taken with other list-based controls, although the details of doing so are left as an exercise for the reader (I love when books do that, implying that it's easy an obvious, but really it's just an indicator that the author didn't get around to trying it themselves yet).

Friday, July 18, 2008

Springtime

Here, finally, is the source code for the Spring effect seen in the video posted on Adobe TV last week. I took my time posting it because I didn't want to spring it on you too suddenly. Or maybe it was the wrong season (not the winter of my discontent, but the summer of my abject laziness). Or more probably, I just had other stuff to do, like code to actually write and check into Flex 4.

But also, tink brought up some good points in the comments to that blog that I wanted to look into and it turns out he was completely correct; there were two problems with my previous version of Spring, as shown in the video. Both are related to memory, although one is more significant than the other.

The first, and most important, issue is that I should have dispose()'d the BitmapData object, in order to release the memory that it had allocated for the bitmap copy of the component. You might think (as I did) that this would be automatically released when its referring objects go away, but that's not the case. Perhaps this is because the BitmapData object can be shared among multiple objects (as in the case of the Bitmap object, which I now use for the sprite), so it's more difficult for the Flash engine to tell when it's not needed anymore.

In any case, you should dispose() a BitmapData object when you no longer need it, particularly in a case like the Spring effect, where we create a new one every time we play the effect. If you bring up TaskManager on Windows, you can see the memory leaking away in nice 64k chunks, which makes sense given that the icons are 128x128, and a bitmap is typically 4 bytes/pixel, so that's 65,536 bytes, or 64k.

Note, however, that you have to wait until you don't need the BitmapData any longer. This is really only the case when the effect ends, as it is used as a source for the drawing while the effect is playing. So the new version of the code declares bmData as an instance variable and calls dispose() in onTweenEnd(), after we're done with it:

        override public function onTweenEnd(value:Object):void
        {
            super.onTweenEnd(value);
            component.stage.removeChild(springer);
            // dispose of the bitmap to release its memory
            bmData.dispose();
        }

The second change issue in the code is much more minor, but could be important in applications that use many more objects than this one. I chose, for no particular reason, to use a Sprite object to hold my bitmap data. But a Sprite is more than I need. All I really want is an object to hold the BitmapData; a Bitmap object is much simpler (both to create and in functionality). So I've changed the code to use that instead of Sprite:

        springer = new Bitmap(bmData, "auto", true);

Check out the source code, or play the demo for yourself: