Source: animate/Timeline.js

animate/Timeline.js

  1. import Tween from './Tween';
  2. /**
  3. * The Timeline class represents a
  4. * @memberof PIXI.animate
  5. * @class Timeline
  6. * @param {PIXI.DisplayObject} Target The target for this string of tweens.
  7. * @extends Array
  8. * @constructor
  9. */
  10. const Timeline = function(target) {
  11. Array.call(this);
  12. /**
  13. * The target DisplayObject.
  14. * @name PIXI.animate.Timeline#target
  15. * @type {PIXI.DisplayObject}
  16. */
  17. this.target = target;
  18. /**
  19. * Current properties in the tween, to make building the timeline more
  20. * efficient.
  21. * @name PIXI.animate.Timeline#_currentProps
  22. * @type {Object}
  23. * @private
  24. */
  25. this._currentProps = {};
  26. };
  27. const p = Timeline.prototype = Object.create(Array.prototype);
  28. /**
  29. * Adds one or more tweens (or timelines) to this timeline. The tweens will be paused (to remove them from the normal ticking system)
  30. * and managed by this timeline. Adding a tween to multiple timelines will result in unexpected behaviour.
  31. * @method PIXI.animate.Timeline#addTween
  32. * @param tween The tween(s) to add. Accepts multiple arguments.
  33. * @return Tween The first tween that was passed in.
  34. */
  35. p.addTween = function(properties, startFrame, duration, ease) {
  36. this.extendLastFrame(startFrame - 1);
  37. //ownership of startProps is passed to the new Tween - this object should not be reused
  38. let startProps = {};
  39. let prop;
  40. //figure out what the starting values for this tween should be
  41. for (prop in properties) {
  42. //if we have already set that property in an earlier tween, use the ending value
  43. if (this._currentProps.hasOwnProperty(prop)) {
  44. startProps[prop] = this._currentProps[prop];
  45. }
  46. //otherwise, get the current value
  47. else {
  48. let startValue = startProps[prop] = this.getPropFromShorthand(prop);
  49. //go through previous tweens to set the value so that when the timeline loops
  50. //around, the values are set properly - having each tween know what came before
  51. //allows us to set to a specific frame without running through the entire timeline
  52. for (let i = this.length - 1; i >= 0; --i) {
  53. this[i].startProps[prop] = startValue;
  54. this[i].endProps[prop] = startValue;
  55. }
  56. }
  57. }
  58. //create the new Tween and add it to the list
  59. let tween = new Tween(this.target, startProps, properties, startFrame, duration, ease);
  60. this.push(tween);
  61. //update starting values for the next tween - if tweened values included 'p', then Tween
  62. //parsed that to add additional data that is required
  63. Object.assign(this._currentProps, tween.endProps);
  64. };
  65. /**
  66. * Add a single keyframe that doesn't tween.
  67. * @method PIXI.animate.Timeline#addKeyframe
  68. * @param {Object} properties The properties to set.
  69. * @param {int} startFrame The starting frame index.
  70. */
  71. p.addKeyframe = function(properties, startFrame) {
  72. this.extendLastFrame(startFrame - 1);
  73. let startProps = Object.assign({}, this._currentProps, properties);
  74. //create the new Tween and add it to the list
  75. let tween = new Tween(this.target, startProps, null, startFrame, 0);
  76. this.push(tween);
  77. Object.assign(this._currentProps, tween.endProps);
  78. };
  79. /**
  80. * Extend the last frame of the tween.
  81. * @method PIXI.animate.Timeline#extendLastFrame
  82. * @param {int} endFrame The ending frame index.
  83. */
  84. p.extendLastFrame = function(endFrame) {
  85. if (this.length) {
  86. let prevTween = this[this.length - 1];
  87. if (prevTween.endFrame < endFrame) {
  88. if (prevTween.isTweenlessFrame) {
  89. prevTween.endFrame = endFrame;
  90. } else {
  91. this.addKeyframe(
  92. this._currentProps,
  93. prevTween.endFrame + 1,
  94. endFrame - prevTween.endFrame + 1
  95. );
  96. }
  97. }
  98. }
  99. };
  100. /**
  101. * Get the value for a property
  102. * @method PIXI.animate.Timeline#getPropFromShorthand
  103. * @param {string} prop
  104. */
  105. p.getPropFromShorthand = function(prop) {
  106. const target = this.target;
  107. switch (prop) {
  108. case 'x':
  109. return target.position.x;
  110. case 'y':
  111. return target.position.y;
  112. case 'sx':
  113. return target.scale.x;
  114. case 'sy':
  115. return target.scale.y;
  116. case 'kx':
  117. return target.skew.x;
  118. case 'ky':
  119. return target.skew.y;
  120. case 'r':
  121. return target.rotation;
  122. case 'a':
  123. return target.alpha;
  124. case 'v':
  125. return target.visible;
  126. case 'm':
  127. return target.mask;
  128. // case 't':
  129. // return target.tint;
  130. //not sure if we'll actually handle graphics this way?
  131. //g: return null;
  132. }
  133. return null;
  134. };
  135. // Assign to namespace
  136. export default Timeline;