PageRenderTime 47ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/joos.anim.js

http://github.com/broofa/joos
JavaScript | 171 lines | 68 code | 24 blank | 79 comment | 20 complexity | 2134afc8db817390a48346f5a4415cf2 MD5 | raw file
  1. (function() {
  2. /**
  3. * joos.Animation provides a framework for animation support. It is not (yet) a
  4. * super-friendly API but, rather, is designed to provide a powerful
  5. * foundation upon which to build.
  6. *
  7. * In most cases, there's no need for you to create your own Animation
  8. * instance. Instead, just use the default instance, 'joos.anim'
  9. */
  10. joos.Animation = joos.createClass({
  11. /* Map of easing functions for manipulating progress. Each function should
  12. * take a value 'x' that represents the progress of the animation (0 =
  13. * start of animation, 1 = end of animation). The returned value should
  14. * generally return a similar progress value (i.e. between 0 and 1). This
  15. * is not mandatory, of course, but values outside this range may produce
  16. * unexpected results, depending on what effect they are applied to
  17. *
  18. * You can see visualizations of these functions here:
  19. * http://fooplot.com/index.php?&y0=sin%28x*pi/2%29&y1=.5-cos%28x*pi%29*.5&y2=sin%28x*pi%29%20%2B%20x*x*x&y3=&y4=x&igx=1&igy=1&igl=1&igs=1&iax=1&ila=1&xmin=-0.5&xmax=1.5&ymin=-0.5&ymax=1.5
  20. */
  21. $EASINGS: {
  22. // Start rapidly, eases into finish
  23. sin: function(x) {return Math.sin(x*Math.PI/2);},
  24. // Eases off start, and into finish, with rapid progress in the middle
  25. cos: function(x) {return .5 - Math.cos(x*Math.PI)*.5;},
  26. // Rapid start, with bounch past finish, and returns to finish.
  27. bounce: function(x) {return Math.sin(x*Math.PI) + x*x*x;},
  28. // Random jitter that settles down to 1
  29. jitter: function(x) {return x + (1-x)*Math.random();},
  30. // Default - 1:1 mapping
  31. linear: function(x) {return x;}
  32. },
  33. /**
  34. * Takes an optional effects params object. See joos.Animation#add for
  35. * more info
  36. */
  37. initialize: function(params) {
  38. this.effects = [];
  39. if (params) this.add(params);
  40. },
  41. /**
  42. * Add an effect to the animation. The following parameters are supported:
  43. *
  44. * block: If true, blocks until all previously added effects have finished
  45. * context: If specified defines a context object for the effect (may
  46. * be any object). Only one effect is allowed per context.
  47. * If a context already has an effect assigned to it, that
  48. * effect is replaced.
  49. * duration: Effect duration, in milliseconds. (default = 500)
  50. * easing:
  51. * finish: If true, effect is immediately finished. onProgress and
  52. * onFinish will both be called exactly once.
  53. * from: The initial value for progress calculation. Default = 0.
  54. * to: The final value for progress calculation. Default = 1.
  55. * onFinish: Callback function invoked when an effect finishes
  56. * onProgress: Callback function invoked for each step in the animation sequence
  57. * onStart: Callback function invoked immediately prior to the effect starting
  58. */
  59. add: function(params) {
  60. var context = params.context;
  61. var effect = context && context._effect;
  62. if (!effect) {
  63. effect = {};
  64. if (context) context._effect = effect;
  65. this.effects.push(effect);
  66. }
  67. // Set/replace params for effect
  68. effect.params = params;
  69. delete effect.t0;
  70. if (!this._timer) {
  71. this._timer = setTimeout(this._step, 0);
  72. }
  73. },
  74. /**
  75. * Shortcut for creating a blocking effect that finishes immediately.
  76. * Useful when you want to instruct the animation to finish a set of added
  77. * effects before beginning another set of effects. E.g.
  78. *
  79. * // Start two simultaneous effects
  80. * joos.anim.add(effect1);
  81. * joos.anim.add(effect2);
  82. *
  83. * // Block until effect1 and effect2 have finished
  84. * joos.anim.block(myCallback);
  85. *
  86. * // These effects will start after effect1 and effect2 have finished
  87. * joos.anim.add(effect3);
  88. * joos.anim.add(effect4);
  89. */
  90. block: function(onFinish) {
  91. this.add({block: true, finish: true, onFinish: onFinish});
  92. },
  93. /**
  94. * Private animation stepper method.
  95. */
  96. bind$_step: function() {
  97. this._timer = null;
  98. var activeEffects = false;
  99. var fx = this.effects, l = fx.length;
  100. var easings = joos.Animation.EASINGS;
  101. var now = new Date().getTime();
  102. // Process each effect
  103. for (var i = 0; i < l; i++) {
  104. var effect = fx[i], params = effect.params;
  105. // If this effect is blocked until previous effects have finished, stop processing
  106. if (params.block && activeEffects) break;
  107. // Okay, there's at least one effect still active
  108. activeEffects = true;
  109. // Calculate the progress for this effect
  110. if (params.onProgress) {
  111. if (!effect.t0) {
  112. effect.t0 = now;
  113. if (params.onStart) params.onStart(params);
  114. }
  115. var dt = now - effect.t0;
  116. var progress = params.finish ? 999 : dt / (params.duration || 500);
  117. effect.animating = progress <= 1.0;
  118. if (!effect.animating) progress = 1;
  119. var easing = params.easing ? easings[params.easing] : easings.linear;
  120. var from = params.from || 0, to = params.to || 1;
  121. progress = from + (to-from)*easing(progress);
  122. // Invoke effect callback
  123. if (params.onProgress) params.onProgress(progress, params);
  124. }
  125. // If this effect is done ...
  126. if (!effect.animating) {
  127. // Call complete callback
  128. if (params.onFinish) params.onFinish(params);
  129. // Remove the effect
  130. if (params.context) delete params.context._effect;
  131. fx[i] = null;
  132. }
  133. }
  134. // Clean up any completed (nulled out) effects
  135. joos.thinArray(fx);
  136. // Keep going(?)
  137. if (fx.length > 0) {
  138. // We don't use setInterval because it has a nasty tendency to queue up
  139. // calls. Using setTimeout insures that we don't schedule anything
  140. // until after the current step has completed
  141. this._timer = setTimeout(this._step, 20);
  142. }
  143. }
  144. });
  145. // Create the default animation object
  146. joos.anim = new joos.Animation();
  147. })();