Anim.html 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-fx-Anim'>/**
  19. </span> * This class manages animation for a specific {@link #target}. The animation allows
  20. * animation of various properties on the target, such as size, position, color and others.
  21. *
  22. * ## Starting Conditions
  23. *
  24. * The starting conditions for the animation are provided by the {@link #from} configuration.
  25. * Any/all of the properties in the {@link #from} configuration can be specified. If a particular
  26. * property is not defined, the starting value for that property will be read directly from the target.
  27. *
  28. * ## End Conditions
  29. *
  30. * The ending conditions for the animation are provided by the {@link #to} configuration. These mark
  31. * the final values once the animations has finished. The values in the {@link #from} can mirror
  32. * those in the {@link #to} configuration to provide a starting point.
  33. *
  34. * ## Other Options
  35. *
  36. * - {@link #duration}: Specifies the time period of the animation.
  37. * - {@link #easing}: Specifies the easing of the animation.
  38. * - {@link #iterations}: Allows the animation to repeat a number of times.
  39. * - {@link #alternate}: Used in conjunction with {@link #iterations}, reverses the direction every second iteration.
  40. *
  41. * ## Example Code
  42. *
  43. * @example
  44. * var myComponent = Ext.create('Ext.Component', {
  45. * renderTo: document.body,
  46. * width: 200,
  47. * height: 200,
  48. * style: 'border: 1px solid red;'
  49. * });
  50. *
  51. * Ext.create('Ext.fx.Anim', {
  52. * target: myComponent,
  53. * duration: 1000,
  54. * from: {
  55. * width: 400 //starting width 400
  56. * },
  57. * to: {
  58. * width: 300, //end width 300
  59. * height: 300 // end height 300
  60. * }
  61. * });
  62. */
  63. Ext.define('Ext.fx.Anim', {
  64. /* Begin Definitions */
  65. mixins: {
  66. observable: 'Ext.util.Observable'
  67. },
  68. requires: ['Ext.fx.Manager', 'Ext.fx.Animator', 'Ext.fx.Easing', 'Ext.fx.CubicBezier', 'Ext.fx.PropertyHandler'],
  69. /* End Definitions */
  70. <span id='Ext-fx-Anim-property-isAnimation'> /**
  71. </span> * @property {Boolean} isAnimation
  72. * `true` in this class to identify an object as an instantiated Anim, or subclass thereof.
  73. */
  74. isAnimation: true,
  75. <span id='Ext-fx-Anim-cfg-callback'> /**
  76. </span> * @cfg {Function} callback
  77. * A function to be run after the animation has completed.
  78. */
  79. <span id='Ext-fx-Anim-cfg-scope'> /**
  80. </span> * @cfg {Function} scope
  81. * The scope that the {@link #callback} function will be called with
  82. */
  83. <span id='Ext-fx-Anim-cfg-duration'> /**
  84. </span> * @cfg {Number} duration
  85. * Time in milliseconds for a single animation to last. If the {@link #iterations} property is
  86. * specified, then each animate will take the same duration for each iteration.
  87. */
  88. duration: 250,
  89. <span id='Ext-fx-Anim-cfg-delay'> /**
  90. </span> * @cfg {Number} delay
  91. * Time to delay before starting the animation.
  92. */
  93. delay: 0,
  94. /* @private used to track a delayed starting time */
  95. delayStart: 0,
  96. <span id='Ext-fx-Anim-cfg-dynamic'> /**
  97. </span> * @cfg {Boolean} dynamic
  98. * Currently only for Component Animation: Only set a component's outer element size bypassing layouts.
  99. * Set to true to do full layouts for every frame of the animation.
  100. */
  101. dynamic: false,
  102. <span id='Ext-fx-Anim-cfg-easing'> /**
  103. </span> * @cfg {String} easing
  104. * This describes how the intermediate values used during a transition will be calculated.
  105. * It allows for a transition to change speed over its duration.
  106. *
  107. * - backIn
  108. * - backOut
  109. * - bounceIn
  110. * - bounceOut
  111. * - ease
  112. * - easeIn
  113. * - easeOut
  114. * - easeInOut
  115. * - elasticIn
  116. * - elasticOut
  117. * - cubic-bezier(x1, y1, x2, y2)
  118. *
  119. * Note that cubic-bezier will create a custom easing curve following the CSS3 [transition-timing-function][0]
  120. * specification. The four values specify points P1 and P2 of the curve as (x1, y1, x2, y2). All values must
  121. * be in the range [0, 1] or the definition is invalid.
  122. *
  123. * [0]: http://www.w3.org/TR/css3-transitions/#transition-timing-function_tag
  124. */
  125. easing: 'ease',
  126. <span id='Ext-fx-Anim-cfg-keyframes'> /**
  127. </span> * @cfg {Object} keyframes
  128. * Animation keyframes follow the CSS3 Animation configuration pattern. 'from' is always considered '0%' and 'to'
  129. * is considered '100%'. **Every keyframe declaration must have a keyframe rule for 0% and 100%, possibly defined using
  130. * &quot;from&quot; or &quot;to&quot;.** A keyframe declaration without these keyframe selectors is invalid and will not be available for
  131. * animation. The keyframe declaration for a keyframe rule consists of properties and values. Properties that are unable to
  132. * be animated are ignored in these rules, with the exception of 'easing' which can be changed at each keyframe. For example:
  133. *
  134. * keyframes : {
  135. * '0%': {
  136. * left: 100
  137. * },
  138. * '40%': {
  139. * left: 150
  140. * },
  141. * '60%': {
  142. * left: 75
  143. * },
  144. * '100%': {
  145. * left: 100
  146. * }
  147. * }
  148. */
  149. <span id='Ext-fx-Anim-property-damper'> /**
  150. </span> * @private
  151. */
  152. damper: 1,
  153. <span id='Ext-fx-Anim-property-bezierRE'> /**
  154. </span> * @private
  155. */
  156. bezierRE: /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,
  157. <span id='Ext-fx-Anim-cfg-reverse'> /**
  158. </span> * Run the animation from the end to the beginning
  159. * Defaults to false.
  160. * @cfg {Boolean} reverse
  161. */
  162. reverse: false,
  163. <span id='Ext-fx-Anim-property-running'> /**
  164. </span> * Flag to determine if the animation has started
  165. * @property running
  166. * @type Boolean
  167. */
  168. running: false,
  169. <span id='Ext-fx-Anim-property-paused'> /**
  170. </span> * Flag to determine if the animation is paused. Only set this to true if you need to
  171. * keep the Anim instance around to be unpaused later; otherwise call {@link #end}.
  172. * @property paused
  173. * @type Boolean
  174. */
  175. paused: false,
  176. <span id='Ext-fx-Anim-cfg-iterations'> /**
  177. </span> * @cfg {Number} iterations
  178. * Number of times to execute the animation.
  179. */
  180. iterations: 1,
  181. <span id='Ext-fx-Anim-cfg-alternate'> /**
  182. </span> * @cfg {Boolean} alternate
  183. * Used in conjunction with iterations to reverse the animation each time an iteration completes.
  184. */
  185. alternate: false,
  186. <span id='Ext-fx-Anim-property-currentIteration'> /**
  187. </span> * Current iteration the animation is running.
  188. * @property currentIteration
  189. * @type Number
  190. */
  191. currentIteration: 0,
  192. <span id='Ext-fx-Anim-property-startTime'> /**
  193. </span> * Starting time of the animation.
  194. * @property startTime
  195. * @type Date
  196. */
  197. startTime: 0,
  198. <span id='Ext-fx-Anim-property-propHandlers'> /**
  199. </span> * Contains a cache of the interpolators to be used.
  200. * @private
  201. * @property propHandlers
  202. * @type Object
  203. */
  204. <span id='Ext-fx-Anim-cfg-target'> /**
  205. </span> * @cfg {String/Object} target
  206. * The {@link Ext.fx.target.Target} to apply the animation to. This should only be specified when creating an Ext.fx.Anim directly.
  207. * The target does not need to be a {@link Ext.fx.target.Target} instance, it can be the underlying object. For example, you can
  208. * pass a Component, Element or Sprite as the target and the Anim will create the appropriate {@link Ext.fx.target.Target} object
  209. * automatically.
  210. */
  211. <span id='Ext-fx-Anim-cfg-from'> /**
  212. </span> * @cfg {Object} from
  213. * An object containing property/value pairs for the beginning of the animation. If not specified, the current state of the
  214. * Ext.fx.target will be used. For example:
  215. *
  216. * from: {
  217. * opacity: 0, // Transparent
  218. * color: '#ffffff', // White
  219. * left: 0
  220. * }
  221. *
  222. */
  223. <span id='Ext-fx-Anim-cfg-to'> /**
  224. </span> * @cfg {Object} to (required)
  225. * An object containing property/value pairs for the end of the animation. For example:
  226. *
  227. * to: {
  228. * opacity: 1, // Opaque
  229. * color: '#00ff00', // Green
  230. * left: 500
  231. * }
  232. *
  233. */
  234. // @private
  235. frameCount: 0,
  236. // @private
  237. constructor: function(config) {
  238. var me = this,
  239. curve;
  240. config = config || {};
  241. // If keyframes are passed, they really want an Animator instead.
  242. if (config.keyframes) {
  243. return new Ext.fx.Animator(config);
  244. }
  245. Ext.apply(me, config);
  246. if (me.from === undefined) {
  247. me.from = {};
  248. }
  249. me.propHandlers = {};
  250. me.config = config;
  251. me.target = Ext.fx.Manager.createTarget(me.target);
  252. me.easingFn = Ext.fx.Easing[me.easing];
  253. me.target.dynamic = me.dynamic;
  254. // If not a pre-defined curve, try a cubic-bezier
  255. if (!me.easingFn) {
  256. me.easingFn = String(me.easing).match(me.bezierRE);
  257. if (me.easingFn &amp;&amp; me.easingFn.length == 5) {
  258. curve = me.easingFn;
  259. me.easingFn = Ext.fx.CubicBezier.cubicBezier(+curve[1], +curve[2], +curve[3], +curve[4]);
  260. }
  261. }
  262. me.id = Ext.id(null, 'ext-anim-');
  263. me.addEvents(
  264. <span id='Ext-fx-Anim-event-beforeanimate'> /**
  265. </span> * @event beforeanimate
  266. * Fires before the animation starts. A handler can return false to cancel the animation.
  267. * @param {Ext.fx.Anim} this
  268. */
  269. 'beforeanimate',
  270. <span id='Ext-fx-Anim-event-afteranimate'> /**
  271. </span> * @event afteranimate
  272. * Fires when the animation is complete.
  273. * @param {Ext.fx.Anim} this
  274. * @param {Date} startTime
  275. */
  276. 'afteranimate',
  277. <span id='Ext-fx-Anim-event-lastframe'> /**
  278. </span> * @event lastframe
  279. * Fires when the animation's last frame has been set.
  280. * @param {Ext.fx.Anim} this
  281. * @param {Date} startTime
  282. */
  283. 'lastframe'
  284. );
  285. me.mixins.observable.constructor.call(me);
  286. Ext.fx.Manager.addAnim(me);
  287. },
  288. <span id='Ext-fx-Anim-method-setAttr'> /**
  289. </span> * @private
  290. * Helper to the target
  291. */
  292. setAttr: function(attr, value) {
  293. return Ext.fx.Manager.items.get(this.id).setAttr(this.target, attr, value);
  294. },
  295. <span id='Ext-fx-Anim-method-initAttrs'> /**
  296. </span> * @private
  297. * Set up the initial currentAttrs hash.
  298. */
  299. initAttrs: function() {
  300. var me = this,
  301. from = me.from,
  302. to = me.to,
  303. initialFrom = me.initialFrom || {},
  304. out = {},
  305. start, end, propHandler, attr;
  306. for (attr in to) {
  307. if (to.hasOwnProperty(attr)) {
  308. start = me.target.getAttr(attr, from[attr]);
  309. end = to[attr];
  310. // Use default (numeric) property handler
  311. if (!Ext.fx.PropertyHandler[attr]) {
  312. if (Ext.isObject(end)) {
  313. propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler.object;
  314. } else {
  315. propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler.defaultHandler;
  316. }
  317. }
  318. // Use custom handler
  319. else {
  320. propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler[attr];
  321. }
  322. out[attr] = propHandler.get(start, end, me.damper, initialFrom[attr], attr);
  323. }
  324. }
  325. me.currentAttrs = out;
  326. },
  327. <span id='Ext-fx-Anim-method-start'> /**
  328. </span> * @private
  329. * Fires beforeanimate and sets the running flag.
  330. */
  331. start: function(startTime) {
  332. var me = this,
  333. delay = me.delay,
  334. delayStart = me.delayStart,
  335. delayDelta;
  336. if (delay) {
  337. if (!delayStart) {
  338. me.delayStart = startTime;
  339. return;
  340. }
  341. else {
  342. delayDelta = startTime - delayStart;
  343. if (delayDelta &lt; delay) {
  344. return;
  345. }
  346. else {
  347. // Compensate for frame delay;
  348. startTime = new Date(delayStart.getTime() + delay);
  349. }
  350. }
  351. }
  352. if (me.fireEvent('beforeanimate', me) !== false) {
  353. me.startTime = startTime;
  354. if (!me.paused &amp;&amp; !me.currentAttrs) {
  355. me.initAttrs();
  356. }
  357. me.running = true;
  358. me.frameCount = 0;
  359. }
  360. },
  361. <span id='Ext-fx-Anim-method-runAnim'> /**
  362. </span> * @private
  363. * Calculate attribute value at the passed timestamp.
  364. * @returns a hash of the new attributes.
  365. */
  366. runAnim: function(elapsedTime) {
  367. var me = this,
  368. attrs = me.currentAttrs,
  369. duration = me.duration,
  370. easingFn = me.easingFn,
  371. propHandlers = me.propHandlers,
  372. ret = {},
  373. easing, values, attr, lastFrame;
  374. if (elapsedTime &gt;= duration) {
  375. elapsedTime = duration;
  376. lastFrame = true;
  377. }
  378. if (me.reverse) {
  379. elapsedTime = duration - elapsedTime;
  380. }
  381. for (attr in attrs) {
  382. if (attrs.hasOwnProperty(attr)) {
  383. values = attrs[attr];
  384. easing = lastFrame ? 1 : easingFn(elapsedTime / duration);
  385. ret[attr] = propHandlers[attr].set(values, easing);
  386. }
  387. }
  388. me.frameCount++;
  389. return ret;
  390. },
  391. <span id='Ext-fx-Anim-method-lastFrame'> /**
  392. </span> * @private
  393. * Perform lastFrame cleanup and handle iterations
  394. * @returns a hash of the new attributes.
  395. */
  396. lastFrame: function() {
  397. var me = this,
  398. iter = me.iterations,
  399. iterCount = me.currentIteration;
  400. iterCount++;
  401. if (iterCount &lt; iter) {
  402. if (me.alternate) {
  403. me.reverse = !me.reverse;
  404. }
  405. me.startTime = new Date();
  406. me.currentIteration = iterCount;
  407. // Turn off paused for CSS3 Transitions
  408. me.paused = false;
  409. }
  410. else {
  411. me.currentIteration = 0;
  412. me.end();
  413. me.fireEvent('lastframe', me, me.startTime);
  414. }
  415. },
  416. endWasCalled: 0,
  417. <span id='Ext-fx-Anim-method-end'> /**
  418. </span> * Fire afteranimate event and end the animation. Usually called automatically when the
  419. * animation reaches its final frame, but can also be called manually to pre-emptively
  420. * stop and destroy the running animation.
  421. */
  422. end: function() {
  423. if (this.endWasCalled++) {
  424. return;
  425. }
  426. var me = this;
  427. me.startTime = 0;
  428. me.paused = false;
  429. me.running = false;
  430. Ext.fx.Manager.removeAnim(me);
  431. me.fireEvent('afteranimate', me, me.startTime);
  432. Ext.callback(me.callback, me.scope, [me, me.startTime]);
  433. },
  434. isReady: function() {
  435. return this.paused === false &amp;&amp; this.running === false &amp;&amp; this.iterations &gt; 0;
  436. },
  437. isRunning: function() {
  438. return this.paused === false &amp;&amp; this.running === true &amp;&amp; this.isAnimator !== true;
  439. }
  440. });
  441. // Set flag to indicate that Fx is available. Class might not be available immediately.
  442. Ext.enableFx = true;
  443. </pre>
  444. </body>
  445. </html>