I would like to share one of my classes I use in (almost) every project, the SleekTween. It is nothing more than an extension of Tweener, although in this case the transition parameter can not be setted.
By now you must be asking yourself, so what is the point? The 20% rule, mentioned in the Flash Animation Tips by Fi, pretty much sums it up:
- The 20% rule. When an animation feels excessive, you can apply what we call the 20% rule. This means that you show only the last portion of an animation flow to the user. For instance, imagine a drop down… instead of animating it expanding all the way down – animate only the last bit where it falls into place. This leads to a shorter animation which focuses on where the dropdown lands and still feels smooth.
With SleekTween it is more precisely a 21.053% rule, and the first bit of the animation is not skipped, it’s only shortened. I have a feeling that many of the Group94 projects have a similar logic of animation.
Click below to check a comparison between SleekTween and Tweener:
Download the source of this example from here sleektween-example.zip (64KB, Flash CS4, Actionscript 3). With FLA file ready to be compiled.
Here’s SleekTween code:
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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | package tv.grifo.transitions { import caurina.transitions.Tweener; /** * @author Grifo.tv / Danilo Figueiredo - www.grifo.tv */ public class SleekTween { //------------------------------------ // private, protected properties //------------------------------------ private static const DIVISOR : Number = 0.5714285714285714; // Number up to 1 private static const FIRST_HALF : Number = 0.21053; // Number up to 1 (FIRST_HALF plus SECOND_HALF should equal 1) private static const SECOND_HALF : Number = 0.78947; // Number up to 1 (FIRST_HALF plus SECOND_HALF should equal 1) //------------------------------------ // public properties //------------------------------------ //------------------------------------ // constructor //------------------------------------ public function SleekTween() { throw new Error("SleekTween is a static class and should not be instantiated."); } // // PRIVATE, PROTECTED //______________________________________________________________________ private static function start(target : Object, parameters : Object) : void { // init tweens var firstTween : Object = {}; var secondTween : Object = {}; // filter properties from parameters var properties : Object = {}; for (var param:String in parameters) { if(target.hasOwnProperty(param)) { properties[param] = parameters[param]; }else if(param != "time" && param != "delay") { trace("Target has no property such as:", param); } } // set tweens properties for (var prop:String in properties) { firstTween[prop] = (properties[prop] - target[prop]) * DIVISOR + target[prop]; secondTween[prop] = properties[prop]; } // set tweens time if (!Boolean(parameters["time"])) parameters["time"] = 2; // set default time to 2 if undefined firstTween["time"] = parameters["time"] * FIRST_HALF; secondTween["time"] = parameters["time"] * SECOND_HALF; // set tweens transition firstTween["transition"] = "easeInExpo"; secondTween["transition"] = "easeOutExpo"; // set tweens delay if (Boolean(parameters["delay"])) { firstTween["delay"] = parameters["delay"]; } else { firstTween["delay"] = 0; } secondTween["delay"] = firstTween["time"] + firstTween["delay"]; secondTween["onComplete"] = parameters["onComplete"]; secondTween["onCompleteParams"] = parameters["onCompleteParams"]; // do tween Tweener.addTween(target, firstTween); Tweener.addTween(target, secondTween); } // // PUBLIC //______________________________________________________________________ public static function addTween(target : Object = null, parameters : Object = null) : void { if (!Boolean(target) || !Boolean(parameters)) return; start(target, parameters); } } } |
Use it like you would use Tweener:
1 | SleekTween.addTween(target, {scaleX:tweenScaleX, time:2}); |
Finally, make sure to apply it whenever it feels right rather than in every single tween animation.
6 Comments
Does look smoother. Why this precise 21.053 number?
I chose this number because it felt right, after a couple of tests. But feel free to change it, just keep in mind that FIRST_HALF plus SECOND_HALF should equal 1.
And regarding the DIVISOR I chose this number because before, back in AS2 tweening with MC Tween, I used to do divide by 1.75 and now, for performance reasons, I multiply by 0.5714285714285714.
That does look smoother.
Hey Danilo,
I’ve made another version of your SleekTween using the TweenLite engine. And I also fixed a bug that was happening when you had more then one instance, like this:
SleekTween.to(shape, 1, { width:0 } );
SleekTween.to(shape, 1, { width:600, delay:1 } );
You can check it out here if you want:
https://gist.github.com/1031877
Thanks for you class, it’s very helpful!
awesome work (:
do you prefer TweenLite than Tweener?
Yes, I do prefer TweenLite instead of Tweener. But I’m trying ZTween (https://github.com/zeh/ztween) on a project that I’m working on.
But I actually don’t see too much difference for most of the stuff.