a zip code crypto-currency system good for red ONLY

animation.js 34KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066
  1. import { isDefined } from '../util/util';
  2. /**
  3. * @hidden
  4. */
  5. export class Animation {
  6. constructor(plt, ele, opts) {
  7. this._dur = null;
  8. this._es = null;
  9. this._rvEs = null;
  10. this.hasChildren = false;
  11. this.isPlaying = false;
  12. this.hasCompleted = false;
  13. this.plt = plt;
  14. this.element(ele);
  15. this.opts = opts;
  16. }
  17. element(ele) {
  18. if (ele) {
  19. if (typeof ele === 'string') {
  20. ele = this.plt.doc().querySelectorAll(ele);
  21. for (let i = 0; i < ele.length; i++) {
  22. this._addEle(ele[i]);
  23. }
  24. }
  25. else if (ele.length) {
  26. for (let i = 0; i < ele.length; i++) {
  27. this._addEle(ele[i]);
  28. }
  29. }
  30. else {
  31. this._addEle(ele);
  32. }
  33. }
  34. return this;
  35. }
  36. /**
  37. * NO DOM
  38. */
  39. _addEle(ele) {
  40. if (ele.nativeElement) {
  41. ele = ele.nativeElement;
  42. }
  43. if (ele.nodeType === 1) {
  44. this._eL = (this._e = this._e || []).push(ele);
  45. }
  46. }
  47. /**
  48. * Add a child animation to this animation.
  49. */
  50. add(childAnimation) {
  51. childAnimation.parent = this;
  52. this.hasChildren = true;
  53. this._cL = (this._c = this._c || []).push(childAnimation);
  54. return this;
  55. }
  56. /**
  57. * Get the duration of this animation. If this animation does
  58. * not have a duration, then it'll get the duration from its parent.
  59. */
  60. getDuration(opts) {
  61. if (opts && isDefined(opts.duration)) {
  62. return opts.duration;
  63. }
  64. else if (this._dur !== null) {
  65. return this._dur;
  66. }
  67. else if (this.parent) {
  68. return this.parent.getDuration();
  69. }
  70. return 0;
  71. }
  72. /**
  73. * Returns if the animation is a root one.
  74. */
  75. isRoot() {
  76. return !this.parent;
  77. }
  78. /**
  79. * Set the duration for this animation.
  80. */
  81. duration(milliseconds) {
  82. this._dur = milliseconds;
  83. return this;
  84. }
  85. /**
  86. * Get the easing of this animation. If this animation does
  87. * not have an easing, then it'll get the easing from its parent.
  88. */
  89. getEasing() {
  90. if (this._rv && this._rvEs) {
  91. return this._rvEs;
  92. }
  93. return this._es !== null ? this._es : (this.parent && this.parent.getEasing()) || null;
  94. }
  95. /**
  96. * Set the easing for this animation.
  97. */
  98. easing(name) {
  99. this._es = name;
  100. return this;
  101. }
  102. /**
  103. * Set the easing for this reversed animation.
  104. */
  105. easingReverse(name) {
  106. this._rvEs = name;
  107. return this;
  108. }
  109. /**
  110. * Add the "from" value for a specific property.
  111. */
  112. from(prop, val) {
  113. this._addProp('from', prop, val);
  114. return this;
  115. }
  116. /**
  117. * Add the "to" value for a specific property.
  118. */
  119. to(prop, val, clearProperyAfterTransition) {
  120. const fx = this._addProp('to', prop, val);
  121. if (clearProperyAfterTransition) {
  122. // if this effect is a transform then clear the transform effect
  123. // otherwise just clear the actual property
  124. this.afterClearStyles([fx.trans ? this.plt.Css.transform : prop]);
  125. }
  126. return this;
  127. }
  128. /**
  129. * Shortcut to add both the "from" and "to" for the same property.
  130. */
  131. fromTo(prop, fromVal, toVal, clearProperyAfterTransition) {
  132. return this.from(prop, fromVal).to(prop, toVal, clearProperyAfterTransition);
  133. }
  134. /**
  135. * @hidden
  136. * NO DOM
  137. */
  138. _getProp(name) {
  139. if (this._fx) {
  140. return this._fx.find((prop) => prop.name === name);
  141. }
  142. else {
  143. this._fx = [];
  144. }
  145. return null;
  146. }
  147. _addProp(state, prop, val) {
  148. let fxProp = this._getProp(prop);
  149. if (!fxProp) {
  150. // first time we've see this EffectProperty
  151. const shouldTrans = (ANIMATION_TRANSFORMS[prop] === 1);
  152. fxProp = {
  153. name: prop,
  154. trans: shouldTrans,
  155. // add the will-change property for transforms or opacity
  156. wc: (shouldTrans ? this.plt.Css.transform : prop)
  157. };
  158. this._fx.push(fxProp);
  159. }
  160. // add from/to EffectState to the EffectProperty
  161. let fxState = {
  162. val: val,
  163. num: null,
  164. unit: '',
  165. };
  166. fxProp[state] = fxState;
  167. if (typeof val === 'string' && val.indexOf(' ') < 0) {
  168. let r = val.match(ANIMATION_CSS_VALUE_REGEX);
  169. let num = parseFloat(r[1]);
  170. if (!isNaN(num)) {
  171. fxState.num = num;
  172. }
  173. fxState.unit = (r[0] !== r[2] ? r[2] : '');
  174. }
  175. else if (typeof val === 'number') {
  176. fxState.num = val;
  177. }
  178. return fxProp;
  179. }
  180. /**
  181. * Add CSS class to this animation's elements
  182. * before the animation begins.
  183. */
  184. beforeAddClass(className) {
  185. (this._bfAdd = this._bfAdd || []).push(className);
  186. return this;
  187. }
  188. /**
  189. * Remove CSS class from this animation's elements
  190. * before the animation begins.
  191. */
  192. beforeRemoveClass(className) {
  193. (this._bfRm = this._bfRm || []).push(className);
  194. return this;
  195. }
  196. /**
  197. * Set CSS inline styles to this animation's elements
  198. * before the animation begins.
  199. */
  200. beforeStyles(styles) {
  201. this._bfSty = styles;
  202. return this;
  203. }
  204. /**
  205. * Clear CSS inline styles from this animation's elements
  206. * before the animation begins.
  207. */
  208. beforeClearStyles(propertyNames) {
  209. this._bfSty = this._bfSty || {};
  210. for (let i = 0; i < propertyNames.length; i++) {
  211. this._bfSty[propertyNames[i]] = '';
  212. }
  213. return this;
  214. }
  215. /**
  216. * Add a function which contains DOM reads, which will run
  217. * before the animation begins.
  218. */
  219. beforeAddRead(domReadFn) {
  220. (this._rdFn = this._rdFn || []).push(domReadFn);
  221. return this;
  222. }
  223. /**
  224. * Add a function which contains DOM writes, which will run
  225. * before the animation begins.
  226. */
  227. beforeAddWrite(domWriteFn) {
  228. (this._wrFn = this._wrFn || []).push(domWriteFn);
  229. return this;
  230. }
  231. /**
  232. * Add CSS class to this animation's elements
  233. * after the animation finishes.
  234. */
  235. afterAddClass(className) {
  236. (this._afAdd = this._afAdd || []).push(className);
  237. return this;
  238. }
  239. /**
  240. * Remove CSS class from this animation's elements
  241. * after the animation finishes.
  242. */
  243. afterRemoveClass(className) {
  244. (this._afRm = this._afRm || []).push(className);
  245. return this;
  246. }
  247. /**
  248. * Set CSS inline styles to this animation's elements
  249. * after the animation finishes.
  250. */
  251. afterStyles(styles) {
  252. this._afSty = styles;
  253. return this;
  254. }
  255. /**
  256. * Clear CSS inline styles from this animation's elements
  257. * after the animation finishes.
  258. */
  259. afterClearStyles(propertyNames) {
  260. this._afSty = this._afSty || {};
  261. for (let i = 0; i < propertyNames.length; i++) {
  262. this._afSty[propertyNames[i]] = '';
  263. }
  264. return this;
  265. }
  266. /**
  267. * Play the animation.
  268. */
  269. play(opts) {
  270. // If the animation was already invalidated (it did finish), do nothing
  271. if (!this.plt) {
  272. return;
  273. }
  274. // this is the top level animation and is in full control
  275. // of when the async play() should actually kick off
  276. // if there is no duration then it'll set the TO property immediately
  277. // if there is a duration, then it'll stage all animations at the
  278. // FROM property and transition duration, wait a few frames, then
  279. // kick off the animation by setting the TO property for each animation
  280. this._isAsync = this._hasDuration(opts);
  281. // ensure all past transition end events have been cleared
  282. this._clearAsync();
  283. // recursively kicks off the correct progress step for each child animation
  284. // ******** DOM WRITE ****************
  285. this._playInit(opts);
  286. // doubling up RAFs since this animation was probably triggered
  287. // from an input event, and just having one RAF would have this code
  288. // run within the same frame as the triggering input event, and the
  289. // input event probably already did way too much work for one frame
  290. this.plt.raf(() => {
  291. this.plt.raf(this._playDomInspect.bind(this, opts));
  292. });
  293. }
  294. syncPlay() {
  295. // If the animation was already invalidated (it did finish), do nothing
  296. if (!this.plt) {
  297. return;
  298. }
  299. const opts = { duration: 0 };
  300. this._isAsync = false;
  301. this._clearAsync();
  302. this._playInit(opts);
  303. this._playDomInspect(opts);
  304. }
  305. /**
  306. * @hidden
  307. * DOM WRITE
  308. * RECURSION
  309. */
  310. _playInit(opts) {
  311. // always default that an animation does not tween
  312. // a tween requires that an Animation class has an element
  313. // and that it has at least one FROM/TO effect
  314. // and that the FROM/TO effect can tween numeric values
  315. this._twn = false;
  316. this.isPlaying = true;
  317. this.hasCompleted = false;
  318. this._hasDur = (this.getDuration(opts) > ANIMATION_DURATION_MIN);
  319. const children = this._c;
  320. for (let i = 0; i < this._cL; i++) {
  321. // ******** DOM WRITE ****************
  322. children[i]._playInit(opts);
  323. }
  324. if (this._hasDur) {
  325. // if there is a duration then we want to start at step 0
  326. // ******** DOM WRITE ****************
  327. this._progress(0);
  328. // add the will-change properties
  329. // ******** DOM WRITE ****************
  330. this._willChg(true);
  331. }
  332. }
  333. /**
  334. * @hidden
  335. * DOM WRITE
  336. * NO RECURSION
  337. * ROOT ANIMATION
  338. */
  339. _playDomInspect(opts) {
  340. // fire off all the "before" function that have DOM READS in them
  341. // elements will be in the DOM, however visibily hidden
  342. // so we can read their dimensions if need be
  343. // ******** DOM READ ****************
  344. // ******** DOM WRITE ****************
  345. this._beforeAnimation();
  346. // for the root animation only
  347. // set the async TRANSITION END event
  348. // and run onFinishes when the transition ends
  349. const dur = this.getDuration(opts);
  350. if (this._isAsync) {
  351. this._asyncEnd(dur, true);
  352. }
  353. // ******** DOM WRITE ****************
  354. this._playProgress(opts);
  355. if (this._isAsync && this.plt) {
  356. // this animation has a duration so we need another RAF
  357. // for the CSS TRANSITION properties to kick in
  358. this.plt.raf(this._playToStep.bind(this, 1));
  359. }
  360. }
  361. /**
  362. * @hidden
  363. * DOM WRITE
  364. * RECURSION
  365. */
  366. _playProgress(opts) {
  367. const children = this._c;
  368. for (let i = 0; i < this._cL; i++) {
  369. // ******** DOM WRITE ****************
  370. children[i]._playProgress(opts);
  371. }
  372. if (this._hasDur) {
  373. // set the CSS TRANSITION duration/easing
  374. // ******** DOM WRITE ****************
  375. this._setTrans(this.getDuration(opts), false);
  376. }
  377. else {
  378. // this animation does not have a duration, so it should not animate
  379. // just go straight to the TO properties and call it done
  380. // ******** DOM WRITE ****************
  381. this._progress(1);
  382. // since there was no animation, immediately run the after
  383. // ******** DOM WRITE ****************
  384. this._setAfterStyles();
  385. // this animation has no duration, so it has finished
  386. // other animations could still be running
  387. this._didFinish(true);
  388. }
  389. }
  390. /**
  391. * @hidden
  392. * DOM WRITE
  393. * RECURSION
  394. */
  395. _playToStep(stepValue) {
  396. const children = this._c;
  397. for (let i = 0; i < this._cL; i++) {
  398. // ******** DOM WRITE ****************
  399. children[i]._playToStep(stepValue);
  400. }
  401. if (this._hasDur) {
  402. // browser had some time to render everything in place
  403. // and the transition duration/easing is set
  404. // now set the TO properties which will trigger the transition to begin
  405. // ******** DOM WRITE ****************
  406. this._progress(stepValue);
  407. }
  408. }
  409. /**
  410. * @hidden
  411. * DOM WRITE
  412. * NO RECURSION
  413. * ROOT ANIMATION
  414. */
  415. _asyncEnd(dur, shouldComplete) {
  416. (void 0) /* assert */;
  417. (void 0) /* assert */;
  418. (void 0) /* assert */;
  419. const self = this;
  420. function onTransitionEnd() {
  421. // congrats! a successful transition completed!
  422. // ensure transition end events and timeouts have been cleared
  423. self._clearAsync();
  424. // ******** DOM WRITE ****************
  425. self._playEnd();
  426. // transition finished
  427. self._didFinishAll(shouldComplete, true, false);
  428. }
  429. function onTransitionFallback() {
  430. (void 0) /* console.debug */;
  431. // oh noz! the transition end event didn't fire in time!
  432. // instead the fallback timer when first
  433. // if all goes well this fallback should never fire
  434. // clear the other async end events from firing
  435. self._tm = undefined;
  436. self._clearAsync();
  437. // set the after styles
  438. // ******** DOM WRITE ****************
  439. self._playEnd(shouldComplete ? 1 : 0);
  440. // transition finished
  441. self._didFinishAll(shouldComplete, true, false);
  442. }
  443. // set the TRANSITION END event on one of the transition elements
  444. self._unrgTrns = this.plt.transitionEnd(self._transEl(), onTransitionEnd, false);
  445. // set a fallback timeout if the transition end event never fires, or is too slow
  446. // transition end fallback: (animation duration + XXms)
  447. self._tm = self.plt.timeout(onTransitionFallback, (dur + ANIMATION_TRANSITION_END_FALLBACK_PADDING_MS));
  448. }
  449. /**
  450. * @hidden
  451. * DOM WRITE
  452. * RECURSION
  453. */
  454. _playEnd(stepValue) {
  455. const children = this._c;
  456. for (let i = 0; i < this._cL; i++) {
  457. // ******** DOM WRITE ****************
  458. children[i]._playEnd(stepValue);
  459. }
  460. if (this._hasDur) {
  461. if (isDefined(stepValue)) {
  462. // too late to have a smooth animation, just finish it
  463. // ******** DOM WRITE ****************
  464. this._setTrans(0, true);
  465. // ensure the ending progress step gets rendered
  466. // ******** DOM WRITE ****************
  467. this._progress(stepValue);
  468. }
  469. // set the after styles
  470. // ******** DOM WRITE ****************
  471. this._setAfterStyles();
  472. // remove the will-change properties
  473. // ******** DOM WRITE ****************
  474. this._willChg(false);
  475. }
  476. }
  477. /**
  478. * @hidden
  479. * NO DOM
  480. * RECURSION
  481. */
  482. _hasDuration(opts) {
  483. if (this.getDuration(opts) > ANIMATION_DURATION_MIN) {
  484. return true;
  485. }
  486. const children = this._c;
  487. for (let i = 0; i < this._cL; i++) {
  488. if (children[i]._hasDuration(opts)) {
  489. return true;
  490. }
  491. }
  492. return false;
  493. }
  494. /**
  495. * @hidden
  496. * NO DOM
  497. * RECURSION
  498. */
  499. _hasDomReads() {
  500. if (this._rdFn && this._rdFn.length) {
  501. return true;
  502. }
  503. const children = this._c;
  504. for (let i = 0; i < this._cL; i++) {
  505. if (children[i]._hasDomReads()) {
  506. return true;
  507. }
  508. }
  509. return false;
  510. }
  511. /**
  512. * Immediately stop at the end of the animation.
  513. */
  514. stop(stepValue = 1) {
  515. // ensure all past transition end events have been cleared
  516. this._clearAsync();
  517. this._hasDur = true;
  518. this._playEnd(stepValue);
  519. }
  520. /**
  521. * @hidden
  522. * NO DOM
  523. * NO RECURSION
  524. */
  525. _clearAsync() {
  526. this._unrgTrns && this._unrgTrns();
  527. this._tm && clearTimeout(this._tm);
  528. this._tm = this._unrgTrns = undefined;
  529. }
  530. /**
  531. * @hidden
  532. * DOM WRITE
  533. * NO RECURSION
  534. */
  535. _progress(stepValue) {
  536. // bread 'n butter
  537. let val;
  538. let effects = this._fx;
  539. let nuElements = this._eL;
  540. if (!effects || !nuElements) {
  541. return;
  542. }
  543. // flip the number if we're going in reverse
  544. if (this._rv) {
  545. stepValue = ((stepValue * -1) + 1);
  546. }
  547. let i, j;
  548. let finalTransform = '';
  549. const elements = this._e;
  550. for (i = 0; i < effects.length; i++) {
  551. const fx = effects[i];
  552. if (fx.from && fx.to) {
  553. const fromNum = fx.from.num;
  554. const toNum = fx.to.num;
  555. const tweenEffect = (fromNum !== toNum);
  556. (void 0) /* assert */;
  557. if (tweenEffect) {
  558. this._twn = true;
  559. }
  560. if (stepValue === 0) {
  561. // FROM
  562. val = fx.from.val;
  563. }
  564. else if (stepValue === 1) {
  565. // TO
  566. val = fx.to.val;
  567. }
  568. else if (tweenEffect) {
  569. // EVERYTHING IN BETWEEN
  570. let valNum = (((toNum - fromNum) * stepValue) + fromNum);
  571. const unit = fx.to.unit;
  572. if (unit === 'px') {
  573. valNum = Math.round(valNum);
  574. }
  575. val = valNum + unit;
  576. }
  577. if (val !== null) {
  578. const prop = fx.name;
  579. if (fx.trans) {
  580. finalTransform += prop + '(' + val + ') ';
  581. }
  582. else {
  583. for (j = 0; j < nuElements; j++) {
  584. // ******** DOM WRITE ****************
  585. elements[j].style[prop] = val;
  586. }
  587. }
  588. }
  589. }
  590. }
  591. // place all transforms on the same property
  592. if (finalTransform.length) {
  593. if (!this._rv && stepValue !== 1 || this._rv && stepValue !== 0) {
  594. finalTransform += 'translateZ(0px)';
  595. }
  596. const cssTransform = this.plt.Css.transform;
  597. for (i = 0; i < elements.length; i++) {
  598. // ******** DOM WRITE ****************
  599. elements[i].style[cssTransform] = finalTransform;
  600. }
  601. }
  602. }
  603. /**
  604. * @hidden
  605. * DOM WRITE
  606. * NO RECURSION
  607. */
  608. _setTrans(dur, forcedLinearEasing) {
  609. // Transition is not enabled if there are not effects
  610. if (!this._fx) {
  611. return;
  612. }
  613. // set the TRANSITION properties inline on the element
  614. const elements = this._e;
  615. const easing = (forcedLinearEasing ? 'linear' : this.getEasing());
  616. const durString = dur + 'ms';
  617. const Css = this.plt.Css;
  618. const cssTransform = Css.transition;
  619. const cssTransitionDuration = Css.transitionDuration;
  620. const cssTransitionTimingFn = Css.transitionTimingFn;
  621. let eleStyle;
  622. for (let i = 0; i < this._eL; i++) {
  623. eleStyle = elements[i].style;
  624. if (dur > 0) {
  625. // ******** DOM WRITE ****************
  626. eleStyle[cssTransform] = '';
  627. eleStyle[cssTransitionDuration] = durString;
  628. // each animation can have a different easing
  629. if (easing) {
  630. // ******** DOM WRITE ****************
  631. eleStyle[cssTransitionTimingFn] = easing;
  632. }
  633. }
  634. else {
  635. eleStyle[cssTransform] = 'none';
  636. }
  637. }
  638. }
  639. /**
  640. * @hidden
  641. * DOM READ
  642. * DOM WRITE
  643. * RECURSION
  644. */
  645. _beforeAnimation() {
  646. // fire off all the "before" function that have DOM READS in them
  647. // elements will be in the DOM, however visibily hidden
  648. // so we can read their dimensions if need be
  649. // ******** DOM READ ****************
  650. this._fireBeforeReadFunc();
  651. // ******** DOM READS ABOVE / DOM WRITES BELOW ****************
  652. // fire off all the "before" function that have DOM WRITES in them
  653. // ******** DOM WRITE ****************
  654. this._fireBeforeWriteFunc();
  655. // stage all of the before css classes and inline styles
  656. // ******** DOM WRITE ****************
  657. this._setBeforeStyles();
  658. }
  659. /**
  660. * @hidden
  661. * DOM WRITE
  662. * RECURSION
  663. */
  664. _setBeforeStyles() {
  665. let i, j;
  666. const children = this._c;
  667. for (i = 0; i < this._cL; i++) {
  668. children[i]._setBeforeStyles();
  669. }
  670. // before the animations have started
  671. // only set before styles if animation is not reversed
  672. if (this._rv) {
  673. return;
  674. }
  675. const addClasses = this._bfAdd;
  676. const removeClasses = this._bfRm;
  677. let ele;
  678. let eleClassList;
  679. let prop;
  680. for (i = 0; i < this._eL; i++) {
  681. ele = this._e[i];
  682. eleClassList = ele.classList;
  683. // css classes to add before the animation
  684. if (addClasses) {
  685. for (j = 0; j < addClasses.length; j++) {
  686. // ******** DOM WRITE ****************
  687. eleClassList.add(addClasses[j]);
  688. }
  689. }
  690. // css classes to remove before the animation
  691. if (removeClasses) {
  692. for (j = 0; j < removeClasses.length; j++) {
  693. // ******** DOM WRITE ****************
  694. eleClassList.remove(removeClasses[j]);
  695. }
  696. }
  697. // inline styles to add before the animation
  698. if (this._bfSty) {
  699. for (prop in this._bfSty) {
  700. // ******** DOM WRITE ****************
  701. ele.style[prop] = this._bfSty[prop];
  702. }
  703. }
  704. }
  705. }
  706. /**
  707. * @hidden
  708. * DOM READ
  709. * RECURSION
  710. */
  711. _fireBeforeReadFunc() {
  712. const children = this._c;
  713. for (let i = 0; i < this._cL; i++) {
  714. // ******** DOM READ ****************
  715. children[i]._fireBeforeReadFunc();
  716. }
  717. const readFunctions = this._rdFn;
  718. if (readFunctions) {
  719. for (let i = 0; i < readFunctions.length; i++) {
  720. // ******** DOM READ ****************
  721. readFunctions[i]();
  722. }
  723. }
  724. }
  725. /**
  726. * @hidden
  727. * DOM WRITE
  728. * RECURSION
  729. */
  730. _fireBeforeWriteFunc() {
  731. const children = this._c;
  732. for (let i = 0; i < this._cL; i++) {
  733. // ******** DOM WRITE ****************
  734. children[i]._fireBeforeWriteFunc();
  735. }
  736. const writeFunctions = this._wrFn;
  737. if (this._wrFn) {
  738. for (let i = 0; i < writeFunctions.length; i++) {
  739. // ******** DOM WRITE ****************
  740. writeFunctions[i]();
  741. }
  742. }
  743. }
  744. /**
  745. * @hidden
  746. * DOM WRITE
  747. */
  748. _setAfterStyles() {
  749. let i, j;
  750. let ele;
  751. let eleClassList;
  752. let elements = this._e;
  753. for (i = 0; i < this._eL; i++) {
  754. ele = elements[i];
  755. eleClassList = ele.classList;
  756. // remove the transition duration/easing
  757. // ******** DOM WRITE ****************
  758. ele.style[this.plt.Css.transitionDuration] = ele.style[this.plt.Css.transitionTimingFn] = '';
  759. if (this._rv) {
  760. // finished in reverse direction
  761. // css classes that were added before the animation should be removed
  762. if (this._bfAdd) {
  763. for (j = 0; j < this._bfAdd.length; j++) {
  764. // ******** DOM WRITE ****************
  765. eleClassList.remove(this._bfAdd[j]);
  766. }
  767. }
  768. // css classes that were removed before the animation should be added
  769. if (this._bfRm) {
  770. for (j = 0; j < this._bfRm.length; j++) {
  771. // ******** DOM WRITE ****************
  772. eleClassList.add(this._bfRm[j]);
  773. }
  774. }
  775. // inline styles that were added before the animation should be removed
  776. if (this._bfSty) {
  777. for (const prop in this._bfSty) {
  778. // ******** DOM WRITE ****************
  779. ele.style[prop] = '';
  780. }
  781. }
  782. }
  783. else {
  784. // finished in forward direction
  785. // css classes to add after the animation
  786. if (this._afAdd) {
  787. for (j = 0; j < this._afAdd.length; j++) {
  788. // ******** DOM WRITE ****************
  789. eleClassList.add(this._afAdd[j]);
  790. }
  791. }
  792. // css classes to remove after the animation
  793. if (this._afRm) {
  794. for (j = 0; j < this._afRm.length; j++) {
  795. // ******** DOM WRITE ****************
  796. eleClassList.remove(this._afRm[j]);
  797. }
  798. }
  799. // inline styles to add after the animation
  800. if (this._afSty) {
  801. for (const prop in this._afSty) {
  802. // ******** DOM WRITE ****************
  803. ele.style[prop] = this._afSty[prop];
  804. }
  805. }
  806. }
  807. }
  808. }
  809. /**
  810. * @hidden
  811. * DOM WRITE
  812. * NO RECURSION
  813. */
  814. _willChg(addWillChange) {
  815. let wc;
  816. let effects = this._fx;
  817. let willChange;
  818. if (addWillChange && effects) {
  819. wc = [];
  820. for (let i = 0; i < effects.length; i++) {
  821. const propWC = effects[i].wc;
  822. if (propWC === 'webkitTransform') {
  823. wc.push('transform', '-webkit-transform');
  824. }
  825. else {
  826. wc.push(propWC);
  827. }
  828. }
  829. willChange = wc.join(',');
  830. }
  831. else {
  832. willChange = '';
  833. }
  834. for (let i = 0; i < this._eL; i++) {
  835. // ******** DOM WRITE ****************
  836. this._e[i].style.willChange = willChange;
  837. }
  838. }
  839. /**
  840. * Start the animation with a user controlled progress.
  841. */
  842. progressStart() {
  843. // ensure all past transition end events have been cleared
  844. this._clearAsync();
  845. // ******** DOM READ/WRITE ****************
  846. this._beforeAnimation();
  847. // ******** DOM WRITE ****************
  848. this._progressStart();
  849. }
  850. /**
  851. * @hidden
  852. * DOM WRITE
  853. * RECURSION
  854. */
  855. _progressStart() {
  856. const children = this._c;
  857. for (let i = 0; i < this._cL; i++) {
  858. // ******** DOM WRITE ****************
  859. children[i]._progressStart();
  860. }
  861. // force no duration, linear easing
  862. // ******** DOM WRITE ****************
  863. this._setTrans(0, true);
  864. // ******** DOM WRITE ****************
  865. this._willChg(true);
  866. }
  867. /**
  868. * Set the progress step for this animation.
  869. * progressStep() is not debounced, so it should not be called faster than 60FPS.
  870. */
  871. progressStep(stepValue) {
  872. // only update if the last update was more than 16ms ago
  873. stepValue = Math.min(1, Math.max(0, stepValue));
  874. const children = this._c;
  875. for (let i = 0; i < this._cL; i++) {
  876. // ******** DOM WRITE ****************
  877. children[i].progressStep(stepValue);
  878. }
  879. if (this._rv) {
  880. // if the animation is going in reverse then
  881. // flip the step value: 0 becomes 1, 1 becomes 0
  882. stepValue = ((stepValue * -1) + 1);
  883. }
  884. // ******** DOM WRITE ****************
  885. this._progress(stepValue);
  886. }
  887. /**
  888. * End the progress animation.
  889. */
  890. progressEnd(shouldComplete, currentStepValue, dur = -1) {
  891. (void 0) /* console.debug */;
  892. if (this._rv) {
  893. // if the animation is going in reverse then
  894. // flip the step value: 0 becomes 1, 1 becomes 0
  895. currentStepValue = ((currentStepValue * -1) + 1);
  896. }
  897. const stepValue = shouldComplete ? 1 : 0;
  898. const diff = Math.abs(currentStepValue - stepValue);
  899. if (diff < 0.05) {
  900. dur = 0;
  901. }
  902. else if (dur < 0) {
  903. dur = this._dur;
  904. }
  905. this._isAsync = (dur > 30);
  906. this._progressEnd(shouldComplete, stepValue, dur, this._isAsync);
  907. if (this._isAsync) {
  908. // for the root animation only
  909. // set the async TRANSITION END event
  910. // and run onFinishes when the transition ends
  911. // ******** DOM WRITE ****************
  912. this._asyncEnd(dur, shouldComplete);
  913. // this animation has a duration so we need another RAF
  914. // for the CSS TRANSITION properties to kick in
  915. this.plt && this.plt.raf(this._playToStep.bind(this, stepValue));
  916. }
  917. }
  918. /**
  919. * @hidden
  920. * DOM WRITE
  921. * RECURSION
  922. */
  923. _progressEnd(shouldComplete, stepValue, dur, isAsync) {
  924. const children = this._c;
  925. for (let i = 0; i < this._cL; i++) {
  926. // ******** DOM WRITE ****************
  927. children[i]._progressEnd(shouldComplete, stepValue, dur, isAsync);
  928. }
  929. if (!isAsync) {
  930. // stop immediately
  931. // set all the animations to their final position
  932. // ******** DOM WRITE ****************
  933. this._progress(stepValue);
  934. this._willChg(false);
  935. this._setAfterStyles();
  936. this._didFinish(shouldComplete);
  937. }
  938. else {
  939. // animate it back to it's ending position
  940. this.isPlaying = true;
  941. this.hasCompleted = false;
  942. this._hasDur = true;
  943. // ******** DOM WRITE ****************
  944. this._willChg(true);
  945. this._setTrans(dur, false);
  946. }
  947. }
  948. /**
  949. * Add a callback to fire when the animation has finished.
  950. */
  951. onFinish(callback, onceTimeCallback = false, clearOnFinishCallacks = false) {
  952. if (clearOnFinishCallacks) {
  953. this._fFn = this._fOneFn = undefined;
  954. }
  955. if (onceTimeCallback) {
  956. this._fOneFn = this._fOneFn || [];
  957. this._fOneFn.push(callback);
  958. }
  959. else {
  960. this._fFn = this._fFn || [];
  961. this._fFn.push(callback);
  962. }
  963. return this;
  964. }
  965. /**
  966. * @hidden
  967. * NO DOM
  968. * RECURSION
  969. */
  970. _didFinishAll(hasCompleted, finishAsyncAnimations, finishNoDurationAnimations) {
  971. const children = this._c;
  972. for (let i = 0; i < this._cL; i++) {
  973. children[i]._didFinishAll(hasCompleted, finishAsyncAnimations, finishNoDurationAnimations);
  974. }
  975. if (finishAsyncAnimations && this._isAsync || finishNoDurationAnimations && !this._isAsync) {
  976. this._didFinish(hasCompleted);
  977. }
  978. }
  979. /**
  980. * @hidden
  981. * NO RECURSION
  982. */
  983. _didFinish(hasCompleted) {
  984. this.isPlaying = false;
  985. this.hasCompleted = hasCompleted;
  986. if (this._fFn) {
  987. // run all finish callbacks
  988. for (let i = 0; i < this._fFn.length; i++) {
  989. this._fFn[i](this);
  990. }
  991. }
  992. if (this._fOneFn) {
  993. // run all "onetime" finish callbacks
  994. for (let i = 0; i < this._fOneFn.length; i++) {
  995. this._fOneFn[i](this);
  996. }
  997. this._fOneFn.length = 0;
  998. }
  999. }
  1000. /**
  1001. * Reverse the animation.
  1002. */
  1003. reverse(shouldReverse = true) {
  1004. const children = this._c;
  1005. for (let i = 0; i < this._cL; i++) {
  1006. children[i].reverse(shouldReverse);
  1007. }
  1008. this._rv = shouldReverse;
  1009. return this;
  1010. }
  1011. /**
  1012. * Recursively destroy this animation and all child animations.
  1013. */
  1014. destroy() {
  1015. const children = this._c;
  1016. for (let i = 0; i < this._cL; i++) {
  1017. children[i].destroy();
  1018. }
  1019. this._clearAsync();
  1020. this.parent = this.plt = this._e = this._rdFn = this._wrFn = null;
  1021. if (this._c) {
  1022. this._c.length = this._cL = 0;
  1023. }
  1024. if (this._fFn) {
  1025. this._fFn.length = 0;
  1026. }
  1027. if (this._fOneFn) {
  1028. this._fOneFn.length = 0;
  1029. }
  1030. }
  1031. /**
  1032. * @hidden
  1033. * NO DOM
  1034. */
  1035. _transEl() {
  1036. // get the lowest level element that has an Animation
  1037. let targetEl;
  1038. for (let i = 0; i < this._cL; i++) {
  1039. targetEl = this._c[i]._transEl();
  1040. if (targetEl) {
  1041. return targetEl;
  1042. }
  1043. }
  1044. return (this._twn && this._hasDur && this._eL ? this._e[0] : null);
  1045. }
  1046. }
  1047. const ANIMATION_TRANSFORMS = {
  1048. 'translateX': 1,
  1049. 'translateY': 1,
  1050. 'translateZ': 1,
  1051. 'scale': 1,
  1052. 'scaleX': 1,
  1053. 'scaleY': 1,
  1054. 'scaleZ': 1,
  1055. 'rotate': 1,
  1056. 'rotateX': 1,
  1057. 'rotateY': 1,
  1058. 'rotateZ': 1,
  1059. 'skewX': 1,
  1060. 'skewY': 1,
  1061. 'perspective': 1
  1062. };
  1063. const ANIMATION_CSS_VALUE_REGEX = /(^-?\d*\.?\d*)(.*)/;
  1064. const ANIMATION_DURATION_MIN = 32;
  1065. const ANIMATION_TRANSITION_END_FALLBACK_PADDING_MS = 400;
  1066. //# sourceMappingURL=animation.js.map