TweenNano.as 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /**
  2. * VERSION: 1.05
  3. * DATE: 2010-05-11
  4. * AS3 (AS2 is also available)
  5. * UPDATES AND DOCUMENTATION AT: http://www.TweenNano.com
  6. **/
  7. package com.greensock {
  8. import flash.display.*;
  9. import flash.events.*;
  10. import flash.utils.*;
  11. /**
  12. * TweenNano is a super-lightweight (1.6k in AS3 and 2k in AS2) version of <a href="http://www.TweenLite.com">TweenLite</a>
  13. * and is only recommended for situations where you absolutely cannot afford the extra 3.1k (4.7k total) that the normal
  14. * TweenLite engine would cost and your project doesn't require any plugins. Normally, it is much better to use
  15. * TweenLite because of the additional flexibility it provides via plugins and its compatibility with TimelineLite and TimelineMax.
  16. * TweenNano can do everything TweenLite can do with the following exceptions:
  17. * <ul>
  18. * <li><b> No Plugins </b>- One of the great things about TweenLite is that you can activate
  19. * plugins in order to add features (like autoAlpha, tint, blurFilter, etc.). TweenNano, however,
  20. * doesn't work with plugins. </li>
  21. *
  22. * <li><b> Incompatible with TimelineLite and TimelineMax </b>- Complex sequencing and management of groups of
  23. * tweens can be much easier with TimelineLite and TimelineMax, but TweenNano instances cannot be inserted into
  24. * TimelineLite or TimelineMax instances.</li>
  25. *
  26. * <li><b> Slight speed decrease </b>- Under very heavy loads, TweenNano won't perform quite as well as TweenLite, but
  27. * it is extremely unlikely that you'd notice unless you're tweening thousands of objects simultaneously.</li>
  28. *
  29. * <li><b> Fewer overwrite modes </b>- You can either overwrite all or none of the existing tweens of the same
  30. * object (overwrite:true or overwrite:false) in TweenNano. TweenLite, however, can use OverwriteManager to expand
  31. * its capabilities and use modes like AUTO, CONCURRENT, PREEXISTING, and ALL_ONSTART
  32. * (see <a href="http://www.greensock.com/overwritemanager/">http://www.greensock.com/overwritemanager/</a>
  33. * for details).</li>
  34. *
  35. * <li><b>Compared to TweenLite, TweenNano is missing the following methods/properties:</b>
  36. * <ul>
  37. * <li>pause()</li>
  38. * <li>play()</li>
  39. * <li>resume()</li>
  40. * <li>restart()</li>
  41. * <li>reverse()</li>
  42. * <li>invalidate()</li>
  43. * <li>onStart</li>
  44. * <li>onInit</li>
  45. * <li>defaultEase</li>
  46. * <li>easeParams</li>
  47. * <li>currentTime</li>
  48. * <li>startTime</li>
  49. * <li>totalTime</li>
  50. * <li>paused</li>
  51. * <li>reversed</li>
  52. * <li>totalDuration</li>
  53. * </ul>
  54. * </li>
  55. * </ul>
  56. *
  57. * <hr/>
  58. * <b>SPECIAL PROPERTIES:</b>
  59. * <br /><br />
  60. *
  61. * Any of the following special properties can optionally be passed in through the vars object (the third parameter):
  62. *
  63. * <ul>
  64. * <li><b> delay : Number</b> Amount of delay in seconds (or frames for frames-based tweens) before the tween should begin.</li>
  65. *
  66. * <li><b> useFrames : Boolean</b> If useFrames is set to true, the tweens's timing mode will be based on frames.
  67. * Otherwise, it will be based on seconds/time.</li>
  68. *
  69. * <li><b> ease : Function</b> Use any standard easing equation to control the rate of change. For example,
  70. * <code>Elastic.easeOut</code>. The Default is Regular.easeOut.</li>
  71. *
  72. * <li><b> onUpdate : Function</b> A function that should be called every time the tween's time/position is updated
  73. * (on every frame while the timeline is active)</li>
  74. *
  75. * <li><b> onUpdateParams : Array</b> An Array of parameters to pass the onUpdate function</li>
  76. *
  77. * <li><b> onComplete : Function</b> A function that should be called when the tween has finished </li>
  78. *
  79. * <li><b> onCompleteParams : Array</b> An Array of parameters to pass the onComplete function.</li>
  80. *
  81. * <li><b> immediateRender : Boolean</b> Normally when you create a from() tween, it renders the starting state immediately even
  82. * if you define a delay which in typical "animate in" scenarios is very desirable, but
  83. * if you prefer to override this behavior and have the from() tween render only after any
  84. * delay has elapsed, set <code>immediateRender</code> to false. </li>
  85. *
  86. * <li><b> overwrite : Boolean</b> Controls how other tweens of the same object are handled when this tween is created. Here are the options:
  87. * <ul>
  88. * <li><b> false (NONE):</b> No tweens are overwritten. This is the fastest mode, but you need to be careful not
  89. * to create any tweens with overlapping properties of the same object that run at the same time,
  90. * otherwise they'll conflict with each other. <br /><code>
  91. * TweenNano.to(mc, 1, {x:100, y:200});<br />
  92. * TweenNano.to(mc, 1, {x:300, delay:2, overwrite:false}); //does NOT overwrite the previous tween.</code></li>
  93. *
  94. * <li><b> true (ALL_IMMEDIATE):</b> This is the default mode in TweenNano. All tweens of the same target
  95. * are completely overwritten immediately when the tween is created, regardless of whether or
  96. * not any of the properties overlap. <br /><code>
  97. * TweenNano.to(mc, 1, {x:100, y:200});<br />
  98. * TweenNano.to(mc, 1, {x:300, delay:2, overwrite:true}); //immediately overwrites the previous tween</code></li>
  99. * </ul></li>
  100. * </ul>
  101. *
  102. * <b>EXAMPLES:</b> <br /><br />
  103. *
  104. * Tween the the MovieClip "mc" to an alpha value of 0.5 (50% transparent) and an x-coordinate of 120
  105. * over the course of 1.5 seconds like so:<br /><br />
  106. *
  107. * <code>
  108. * import com.greensock.TweenNano;<br /><br />
  109. * TweenNano.to(mc, 1.5, {alpha:0.5, x:120});
  110. * </code><br /><br />
  111. *
  112. * To tween the "mc" MovieClip's alpha property to 0.5, its x property to 120 using the <code>Back.easeOut</code> easing
  113. * function, delay starting the whole tween by 2 seconds, and then call a function named "onFinishTween" when it
  114. * has completed (it will have a duration of 5 seconds) and pass a few parameters to that function (a value of
  115. * 5 and a reference to the mc), you'd do so like:<br /><br />
  116. *
  117. * <code>
  118. * import com.greensock.TweenNano;<br />
  119. * import com.greensock.easing.Back;<br /><br />
  120. *
  121. * TweenNano.to(mc, 5, {alpha:0.5, x:120, ease:Back.easeOut, delay:2, onComplete:onFinishTween, onCompleteParams:[5, mc]});<br />
  122. * function onFinishTween(param1:Number, param2:MovieClip):void {<br />
  123. * trace("The tween has finished! param1 = " + param1 + ", and param2 = " + param2);<br />
  124. * }
  125. * </code><br /><br />
  126. *
  127. * If you have a MovieClip on the stage that is already in it's end position and you just want to animate it into
  128. * place over 5 seconds (drop it into place by changing its y property to 100 pixels higher on the screen and
  129. * dropping it from there), you could:<br /><br />
  130. *
  131. * <code>
  132. * import com.greensock.TweenNano;<br />
  133. * import com.greensock.easing.Elastic;<br /><br />
  134. *
  135. * TweenNano.from(mc, 5, {y:"-100", ease:Elastic.easeOut});
  136. * </code><br /><br />
  137. *
  138. * <b>NOTES:</b><br /><br />
  139. * <ul>
  140. * <li> The base TweenNano class adds about 1.6k to your Flash file.</li>
  141. *
  142. * <li> Passing values as Strings will make the tween relative to the current value. For example, if you do
  143. * <code>TweenNano.to(mc, 2, {x:"-20"});</code> it'll move the mc.x to the left 20 pixels which is the same as doing
  144. * <code>TweenNano.to(mc, 2, {x:mc.x - 20});</code> You could also cast it like: <code>TweenNano.to(mc, 2, {x:String(myVariable)});</code></li>
  145. *
  146. * <li> Kill all tweens for a particular object anytime with the <code>TweenNano.killTweensOf(mc); </code></li>
  147. *
  148. * <li> You can kill all delayedCalls to a particular function using <code>TweenNano.killTweensOf(myFunction);</code>
  149. * This can be helpful if you want to preempt a call.</li>
  150. *
  151. * <li> If some of your tweens don't appear to be working, read about the <code>overwrite</code> special property
  152. * above - it is most likely an overwriting issue that could be solved by adding <code>overwrite:false</code> to your vars object.</li>
  153. *
  154. * <li> Use the <code>TweenNano.from()</code> method to animate things into place. For example, if you have things set up on
  155. * the stage in the spot where they should end up, and you just want to animate them into place, you can
  156. * pass in the beginning x and/or y and/or alpha (or whatever properties you want).</li>
  157. *
  158. * <li> If you find this class useful, please consider joining Club GreenSock which not only helps to sustain
  159. * ongoing development, but also gets you bonus plugins, classes and other benefits that are ONLY available
  160. * to members. Learn more at <a href="http://www.greensock.com/club/">http://www.greensock.com/club/</a></li>
  161. * </ul>
  162. *
  163. * <b>Copyright 2010, GreenSock. All rights reserved.</b> This work is subject to the terms in <a href="http://www.greensock.com/terms_of_use.html">http://www.greensock.com/terms_of_use.html</a> or for corporate Club GreenSock members, the software agreement that was issued with the corporate membership.
  164. *
  165. * @author Jack Doyle, jack@greensock.com
  166. */
  167. public class TweenNano {
  168. /** @private **/
  169. protected static var _time:Number;
  170. /** @private **/
  171. protected static var _frame:uint;
  172. /** @private Holds references to all our tweens based on their targets (an Array for each target) **/
  173. protected static var _masterList:Dictionary = new Dictionary(false);
  174. /** @private A reference to the Shape that we use to drive all our ENTER_FRAME events. **/
  175. protected static var _shape:Shape = new Shape();
  176. /** @private Indicates whether or not the TweenNano class has been initted. **/
  177. protected static var _tnInitted:Boolean;
  178. /** @private **/
  179. protected static var _reservedProps:Object = {ease:1, delay:1, useFrames:1, overwrite:1, onComplete:1, onCompleteParams:1, runBackwards:1, immediateRender:1, onUpdate:1, onUpdateParams:1};
  180. /** Duration of the tween in seconds (or in frames if "useFrames" is true). **/
  181. public var duration:Number;
  182. /** Stores variables (things like "alpha", "y" or whatever we're tweening, as well as special properties like "onComplete"). **/
  183. public var vars:Object;
  184. /** @private Start time in seconds (or frames for frames-based tweens) **/
  185. public var startTime:Number;
  186. /** Target object whose properties this tween affects. This can be ANY object, not just a DisplayObject. **/
  187. public var target:Object;
  188. /** @private Indicates whether or not the tween is currently active **/
  189. public var active:Boolean;
  190. /** @private Flagged for garbage collection **/
  191. public var gc:Boolean;
  192. /** Indicates that frames should be used instead of seconds for timing purposes. So if useFrames is true and the tween's duration is 10, it would mean that the tween should take 10 frames to complete, not 10 seconds. **/
  193. public var useFrames:Boolean;
  194. /** @private result of _ease(this.time, 0, 1, this.duration). Usually between 0 and 1, but not always (like with Elastic.easeOut). **/
  195. public var ratio:Number = 0;
  196. /** @private Easing method to use which determines how the values animate over time. Examples are Elastic.easeOut and Strong.easeIn. Many are found in the fl.motion.easing package or com.greensock.easing. **/
  197. protected var _ease:Function;
  198. /** @private Indicates whether or not init() has been called (where all the tween property start/end value information is recorded) **/
  199. protected var _initted:Boolean;
  200. /** @private Contains parsed data for each property that's being tweened (property name, start, and change) **/
  201. protected var _propTweens:Array;
  202. /**
  203. * Constructor
  204. *
  205. * @param target Target object whose properties this tween affects. This can be ANY object, not just a DisplayObject.
  206. * @param duration Duration in seconds (or in frames if "useFrames" is true)
  207. * @param vars An object containing the end values of the properties you're tweening, like {x:100, y:50}. It can also contain special properties like "onComplete", "ease", "delay", etc.
  208. */
  209. public function TweenNano(target:Object, duration:Number, vars:Object) {
  210. if (!_tnInitted) {
  211. _time = getTimer() * 0.001;
  212. _frame = 0;
  213. _shape.addEventListener(Event.ENTER_FRAME, updateAll, false, 0, true);
  214. _tnInitted = true;
  215. }
  216. this.vars = vars;
  217. this.duration = duration;
  218. this.active = Boolean(duration == 0 && this.vars.delay == 0 && this.vars.immediateRender != false);
  219. this.target = target;
  220. if (typeof(this.vars.ease) != "function") {
  221. _ease = TweenNano.easeOut;
  222. } else {
  223. _ease = this.vars.ease;
  224. }
  225. _propTweens = [];
  226. this.useFrames = Boolean(vars.useFrames == true);
  227. var delay:Number = ("delay" in this.vars) ? Number(this.vars.delay) : 0;
  228. this.startTime = (this.useFrames) ? _frame + delay : _time + delay;
  229. var a:Array = _masterList[target];
  230. if (a == null || int(this.vars.overwrite) == 1 || this.vars.overwrite == null) {
  231. _masterList[target] = [this];
  232. } else {
  233. a[a.length] = this;
  234. }
  235. if (this.vars.immediateRender == true || this.active) {
  236. renderTime(0);
  237. }
  238. }
  239. /**
  240. * @private
  241. * Initializes the property tweens, determining their start values and amount of change.
  242. * Also triggers overwriting if necessary and sets the _hasUpdate variable.
  243. */
  244. public function init():void {
  245. for (var p:String in this.vars) {
  246. if (!(p in _reservedProps)) {
  247. _propTweens[_propTweens.length] = [p, this.target[p], (typeof(this.vars[p]) == "number") ? this.vars[p] - this.target[p] : Number(this.vars[p])]; //[property, start, change]
  248. }
  249. }
  250. if (this.vars.runBackwards) {
  251. var pt:Array;
  252. var i:int = _propTweens.length;
  253. while (--i > -1) {
  254. pt = _propTweens[i];
  255. pt[1] += pt[2];
  256. pt[2] = -pt[2];
  257. }
  258. }
  259. _initted = true;
  260. }
  261. /**
  262. * Renders the tween at a particular time (or frame number for frames-based tweens)
  263. * WITHOUT changing its startTime, meaning if the tween is in progress when you call
  264. * renderTime(), it will not adjust the tween's timing to continue from the new time.
  265. * The time is based simply on the overall duration. For example, if a tween's duration
  266. * is 3, renderTime(1.5) would render it at the halfway finished point.
  267. *
  268. * @param time time (or frame number for frames-based tweens) to render.
  269. */
  270. public function renderTime(time:Number):void {
  271. if (!_initted) {
  272. init();
  273. }
  274. var pt:Array, i:int = _propTweens.length;
  275. if (time >= this.duration) {
  276. time = this.duration;
  277. this.ratio = 1;
  278. } else if (time <= 0) {
  279. this.ratio = 0;
  280. } else {
  281. this.ratio = _ease(time, 0, 1, this.duration);
  282. }
  283. while (--i > -1) {
  284. pt = _propTweens[i];
  285. this.target[pt[0]] = pt[1] + (this.ratio * pt[2]);
  286. }
  287. if (this.vars.onUpdate) {
  288. this.vars.onUpdate.apply(null, this.vars.onUpdateParams);
  289. }
  290. if (time == this.duration) {
  291. complete(true);
  292. }
  293. }
  294. /**
  295. * Forces the tween to completion.
  296. *
  297. * @param skipRender To skip rendering the final state of the tween, set skipRender to true.
  298. */
  299. public function complete(skipRender:Boolean=false):void {
  300. if (!skipRender) {
  301. renderTime(this.duration);
  302. return;
  303. }
  304. kill();
  305. if (this.vars.onComplete) {
  306. this.vars.onComplete.apply(null, this.vars.onCompleteParams);
  307. }
  308. }
  309. /** Kills the tween, stopping it immediately. **/
  310. public function kill():void {
  311. this.gc = true;
  312. this.active = false;
  313. }
  314. //---- STATIC FUNCTIONS -------------------------------------------------------------------------
  315. /**
  316. * Static method for creating a TweenNano instance which can be more intuitive for some developers
  317. * and shields them from potential garbage collection issues that could arise when assigning a
  318. * tween instance to a variable that persists. The following lines of code all produce exactly
  319. * the same result: <br /><br /><code>
  320. *
  321. * var myTween:TweenNano = new TweenNano(mc, 1, {x:100}); <br />
  322. * TweenNano.to(mc, 1, {x:100}); <br />
  323. * var myTween:TweenNano = TweenNano.to(mc, 1, {x:100});</code>
  324. *
  325. * @param target Target object whose properties this tween affects. This can be ANY object, not just a DisplayObject.
  326. * @param duration Duration in seconds (or frames if "useFrames" is true)
  327. * @param vars An object containing the end values of the properties you're tweening, like {x:100, y:50}. It can also contain special properties like "onComplete", "ease", "delay", etc.
  328. * @return TweenNano instance
  329. */
  330. public static function to(target:Object, duration:Number, vars:Object):TweenNano {
  331. return new TweenNano(target, duration, vars);
  332. }
  333. /**
  334. * Static method for creating a TweenNano instance that tweens in the opposite direction
  335. * compared to a TweenNano.to() tween. In other words, you define the START values in the
  336. * vars object instead of the end values, and the tween will use the current values as
  337. * the end values. This can be very useful for animating things into place on the stage
  338. * because you can build them in their end positions and do some simple TweenNano.from()
  339. * calls to animate them into place. <b>NOTE:</b> By default, <code>immediateRender</code>
  340. * is <code>true</code> in from() tweens, meaning that they immediately render their starting state
  341. * regardless of any delay that is specified. You can override this behavior by passing
  342. * <code>immediateRender:false</code> in the <code>vars</code> object so that it will wait to
  343. * render until the tween actually begins. To illustrate the default behavior, the following code
  344. * will immediately set the <code>alpha</code> of <code>mc</code> to 0 and then wait 2 seconds
  345. * before tweening the <code>alpha</code> back to 1 over the course of 1.5 seconds:<br /><br /><code>
  346. *
  347. * TweenNano.from(mc, 1.5, {alpha:0, delay:2});</code>
  348. *
  349. * @param target Target object whose properties this tween affects. This can be ANY object, not just a DisplayObject.
  350. * @param duration Duration in seconds (or frames if "useFrames" is true)
  351. * @param vars An object containing the start values of the properties you're tweening like {x:100, y:50}. It can also contain special properties like "onComplete", "ease", "delay", etc.
  352. * @return TweenNano instance
  353. */
  354. public static function from(target:Object, duration:Number, vars:Object):TweenNano {
  355. vars.runBackwards = true;
  356. if (!("immediateRender" in vars)) {
  357. vars.immediateRender = true;
  358. }
  359. return new TweenNano(target, duration, vars);
  360. }
  361. /**
  362. * Provides a simple way to call a function after a set amount of time (or frames). You can
  363. * optionally pass any number of parameters to the function too. For example:<br /><br /><code>
  364. *
  365. * TweenNano.delayedCall(1, myFunction, ["param1", 2]); <br />
  366. * function myFunction(param1:String, param2:Number):void { <br />
  367. * trace("called myFunction and passed params: " + param1 + ", " + param2); <br />
  368. * } </code>
  369. *
  370. * @param delay Delay in seconds (or frames if "useFrames" is true) before the function should be called
  371. * @param onComplete Function to call
  372. * @param onCompleteParams An Array of parameters to pass the function.
  373. * @param useFrames If the delay should be measured in frames instead of seconds, set useFrames to true (default is false)
  374. * @return TweenNano instance
  375. */
  376. public static function delayedCall(delay:Number, onComplete:Function, onCompleteParams:Array=null, useFrames:Boolean=false):TweenNano {
  377. return new TweenNano(onComplete, 0, {delay:delay, onComplete:onComplete, onCompleteParams:onCompleteParams, useFrames:useFrames, overwrite:0});
  378. }
  379. /**
  380. * @private
  381. * Updates active tweens and activates those whose startTime is before the _time/_frame.
  382. *
  383. * @param e ENTER_FRAME Event
  384. */
  385. public static function updateAll(e:Event=null):void {
  386. _frame++;
  387. _time = getTimer() * 0.001;
  388. var ml:Dictionary = _masterList, a:Array, tgt:Object, i:int, t:Number, tween:TweenNano;
  389. for (tgt in ml) {
  390. a = ml[tgt];
  391. i = a.length;
  392. while (--i > -1) {
  393. tween = a[i];
  394. t = (tween.useFrames) ? _frame : _time;
  395. if (tween.active || (!tween.gc && t >= tween.startTime)) {
  396. tween.renderTime(t - tween.startTime);
  397. } else if (tween.gc) {
  398. a.splice(i, 1);
  399. }
  400. }
  401. if (a.length == 0) {
  402. delete ml[tgt];
  403. }
  404. }
  405. }
  406. /**
  407. * Kills all the tweens of a particular object, optionally forcing them to completion too.
  408. *
  409. * @param target Object whose tweens should be immediately killed
  410. * @param complete Indicates whether or not the tweens should be forced to completion before being killed.
  411. */
  412. public static function killTweensOf(target:Object, complete:Boolean=false):void {
  413. if (target in _masterList) {
  414. if (complete) {
  415. var a:Array = _masterList[target];
  416. var i:int = a.length;
  417. while (--i > -1) {
  418. if (!TweenNano(a[i]).gc) {
  419. TweenNano(a[i]).complete(false);
  420. }
  421. }
  422. }
  423. delete _masterList[target];
  424. }
  425. }
  426. /** @private **/
  427. private static function easeOut(t:Number, b:Number, c:Number, d:Number):Number {
  428. return -1 * (t /= d) * (t - 2);
  429. }
  430. }
  431. }