1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066 |
- import { isDefined } from '../util/util';
- /**
- * @hidden
- */
- export class Animation {
- constructor(plt, ele, opts) {
- this._dur = null;
- this._es = null;
- this._rvEs = null;
- this.hasChildren = false;
- this.isPlaying = false;
- this.hasCompleted = false;
- this.plt = plt;
- this.element(ele);
- this.opts = opts;
- }
- element(ele) {
- if (ele) {
- if (typeof ele === 'string') {
- ele = this.plt.doc().querySelectorAll(ele);
- for (let i = 0; i < ele.length; i++) {
- this._addEle(ele[i]);
- }
- }
- else if (ele.length) {
- for (let i = 0; i < ele.length; i++) {
- this._addEle(ele[i]);
- }
- }
- else {
- this._addEle(ele);
- }
- }
- return this;
- }
- /**
- * NO DOM
- */
- _addEle(ele) {
- if (ele.nativeElement) {
- ele = ele.nativeElement;
- }
- if (ele.nodeType === 1) {
- this._eL = (this._e = this._e || []).push(ele);
- }
- }
- /**
- * Add a child animation to this animation.
- */
- add(childAnimation) {
- childAnimation.parent = this;
- this.hasChildren = true;
- this._cL = (this._c = this._c || []).push(childAnimation);
- return this;
- }
- /**
- * Get the duration of this animation. If this animation does
- * not have a duration, then it'll get the duration from its parent.
- */
- getDuration(opts) {
- if (opts && isDefined(opts.duration)) {
- return opts.duration;
- }
- else if (this._dur !== null) {
- return this._dur;
- }
- else if (this.parent) {
- return this.parent.getDuration();
- }
- return 0;
- }
- /**
- * Returns if the animation is a root one.
- */
- isRoot() {
- return !this.parent;
- }
- /**
- * Set the duration for this animation.
- */
- duration(milliseconds) {
- this._dur = milliseconds;
- return this;
- }
- /**
- * Get the easing of this animation. If this animation does
- * not have an easing, then it'll get the easing from its parent.
- */
- getEasing() {
- if (this._rv && this._rvEs) {
- return this._rvEs;
- }
- return this._es !== null ? this._es : (this.parent && this.parent.getEasing()) || null;
- }
- /**
- * Set the easing for this animation.
- */
- easing(name) {
- this._es = name;
- return this;
- }
- /**
- * Set the easing for this reversed animation.
- */
- easingReverse(name) {
- this._rvEs = name;
- return this;
- }
- /**
- * Add the "from" value for a specific property.
- */
- from(prop, val) {
- this._addProp('from', prop, val);
- return this;
- }
- /**
- * Add the "to" value for a specific property.
- */
- to(prop, val, clearProperyAfterTransition) {
- const fx = this._addProp('to', prop, val);
- if (clearProperyAfterTransition) {
- // if this effect is a transform then clear the transform effect
- // otherwise just clear the actual property
- this.afterClearStyles([fx.trans ? this.plt.Css.transform : prop]);
- }
- return this;
- }
- /**
- * Shortcut to add both the "from" and "to" for the same property.
- */
- fromTo(prop, fromVal, toVal, clearProperyAfterTransition) {
- return this.from(prop, fromVal).to(prop, toVal, clearProperyAfterTransition);
- }
- /**
- * @hidden
- * NO DOM
- */
- _getProp(name) {
- if (this._fx) {
- return this._fx.find((prop) => prop.name === name);
- }
- else {
- this._fx = [];
- }
- return null;
- }
- _addProp(state, prop, val) {
- let fxProp = this._getProp(prop);
- if (!fxProp) {
- // first time we've see this EffectProperty
- const shouldTrans = (ANIMATION_TRANSFORMS[prop] === 1);
- fxProp = {
- name: prop,
- trans: shouldTrans,
- // add the will-change property for transforms or opacity
- wc: (shouldTrans ? this.plt.Css.transform : prop)
- };
- this._fx.push(fxProp);
- }
- // add from/to EffectState to the EffectProperty
- let fxState = {
- val: val,
- num: null,
- unit: '',
- };
- fxProp[state] = fxState;
- if (typeof val === 'string' && val.indexOf(' ') < 0) {
- let r = val.match(ANIMATION_CSS_VALUE_REGEX);
- let num = parseFloat(r[1]);
- if (!isNaN(num)) {
- fxState.num = num;
- }
- fxState.unit = (r[0] !== r[2] ? r[2] : '');
- }
- else if (typeof val === 'number') {
- fxState.num = val;
- }
- return fxProp;
- }
- /**
- * Add CSS class to this animation's elements
- * before the animation begins.
- */
- beforeAddClass(className) {
- (this._bfAdd = this._bfAdd || []).push(className);
- return this;
- }
- /**
- * Remove CSS class from this animation's elements
- * before the animation begins.
- */
- beforeRemoveClass(className) {
- (this._bfRm = this._bfRm || []).push(className);
- return this;
- }
- /**
- * Set CSS inline styles to this animation's elements
- * before the animation begins.
- */
- beforeStyles(styles) {
- this._bfSty = styles;
- return this;
- }
- /**
- * Clear CSS inline styles from this animation's elements
- * before the animation begins.
- */
- beforeClearStyles(propertyNames) {
- this._bfSty = this._bfSty || {};
- for (let i = 0; i < propertyNames.length; i++) {
- this._bfSty[propertyNames[i]] = '';
- }
- return this;
- }
- /**
- * Add a function which contains DOM reads, which will run
- * before the animation begins.
- */
- beforeAddRead(domReadFn) {
- (this._rdFn = this._rdFn || []).push(domReadFn);
- return this;
- }
- /**
- * Add a function which contains DOM writes, which will run
- * before the animation begins.
- */
- beforeAddWrite(domWriteFn) {
- (this._wrFn = this._wrFn || []).push(domWriteFn);
- return this;
- }
- /**
- * Add CSS class to this animation's elements
- * after the animation finishes.
- */
- afterAddClass(className) {
- (this._afAdd = this._afAdd || []).push(className);
- return this;
- }
- /**
- * Remove CSS class from this animation's elements
- * after the animation finishes.
- */
- afterRemoveClass(className) {
- (this._afRm = this._afRm || []).push(className);
- return this;
- }
- /**
- * Set CSS inline styles to this animation's elements
- * after the animation finishes.
- */
- afterStyles(styles) {
- this._afSty = styles;
- return this;
- }
- /**
- * Clear CSS inline styles from this animation's elements
- * after the animation finishes.
- */
- afterClearStyles(propertyNames) {
- this._afSty = this._afSty || {};
- for (let i = 0; i < propertyNames.length; i++) {
- this._afSty[propertyNames[i]] = '';
- }
- return this;
- }
- /**
- * Play the animation.
- */
- play(opts) {
- // If the animation was already invalidated (it did finish), do nothing
- if (!this.plt) {
- return;
- }
- // this is the top level animation and is in full control
- // of when the async play() should actually kick off
- // if there is no duration then it'll set the TO property immediately
- // if there is a duration, then it'll stage all animations at the
- // FROM property and transition duration, wait a few frames, then
- // kick off the animation by setting the TO property for each animation
- this._isAsync = this._hasDuration(opts);
- // ensure all past transition end events have been cleared
- this._clearAsync();
- // recursively kicks off the correct progress step for each child animation
- // ******** DOM WRITE ****************
- this._playInit(opts);
- // doubling up RAFs since this animation was probably triggered
- // from an input event, and just having one RAF would have this code
- // run within the same frame as the triggering input event, and the
- // input event probably already did way too much work for one frame
- this.plt.raf(() => {
- this.plt.raf(this._playDomInspect.bind(this, opts));
- });
- }
- syncPlay() {
- // If the animation was already invalidated (it did finish), do nothing
- if (!this.plt) {
- return;
- }
- const opts = { duration: 0 };
- this._isAsync = false;
- this._clearAsync();
- this._playInit(opts);
- this._playDomInspect(opts);
- }
- /**
- * @hidden
- * DOM WRITE
- * RECURSION
- */
- _playInit(opts) {
- // always default that an animation does not tween
- // a tween requires that an Animation class has an element
- // and that it has at least one FROM/TO effect
- // and that the FROM/TO effect can tween numeric values
- this._twn = false;
- this.isPlaying = true;
- this.hasCompleted = false;
- this._hasDur = (this.getDuration(opts) > ANIMATION_DURATION_MIN);
- const children = this._c;
- for (let i = 0; i < this._cL; i++) {
- // ******** DOM WRITE ****************
- children[i]._playInit(opts);
- }
- if (this._hasDur) {
- // if there is a duration then we want to start at step 0
- // ******** DOM WRITE ****************
- this._progress(0);
- // add the will-change properties
- // ******** DOM WRITE ****************
- this._willChg(true);
- }
- }
- /**
- * @hidden
- * DOM WRITE
- * NO RECURSION
- * ROOT ANIMATION
- */
- _playDomInspect(opts) {
- // fire off all the "before" function that have DOM READS in them
- // elements will be in the DOM, however visibily hidden
- // so we can read their dimensions if need be
- // ******** DOM READ ****************
- // ******** DOM WRITE ****************
- this._beforeAnimation();
- // for the root animation only
- // set the async TRANSITION END event
- // and run onFinishes when the transition ends
- const dur = this.getDuration(opts);
- if (this._isAsync) {
- this._asyncEnd(dur, true);
- }
- // ******** DOM WRITE ****************
- this._playProgress(opts);
- if (this._isAsync && this.plt) {
- // this animation has a duration so we need another RAF
- // for the CSS TRANSITION properties to kick in
- this.plt.raf(this._playToStep.bind(this, 1));
- }
- }
- /**
- * @hidden
- * DOM WRITE
- * RECURSION
- */
- _playProgress(opts) {
- const children = this._c;
- for (let i = 0; i < this._cL; i++) {
- // ******** DOM WRITE ****************
- children[i]._playProgress(opts);
- }
- if (this._hasDur) {
- // set the CSS TRANSITION duration/easing
- // ******** DOM WRITE ****************
- this._setTrans(this.getDuration(opts), false);
- }
- else {
- // this animation does not have a duration, so it should not animate
- // just go straight to the TO properties and call it done
- // ******** DOM WRITE ****************
- this._progress(1);
- // since there was no animation, immediately run the after
- // ******** DOM WRITE ****************
- this._setAfterStyles();
- // this animation has no duration, so it has finished
- // other animations could still be running
- this._didFinish(true);
- }
- }
- /**
- * @hidden
- * DOM WRITE
- * RECURSION
- */
- _playToStep(stepValue) {
- const children = this._c;
- for (let i = 0; i < this._cL; i++) {
- // ******** DOM WRITE ****************
- children[i]._playToStep(stepValue);
- }
- if (this._hasDur) {
- // browser had some time to render everything in place
- // and the transition duration/easing is set
- // now set the TO properties which will trigger the transition to begin
- // ******** DOM WRITE ****************
- this._progress(stepValue);
- }
- }
- /**
- * @hidden
- * DOM WRITE
- * NO RECURSION
- * ROOT ANIMATION
- */
- _asyncEnd(dur, shouldComplete) {
- (void 0) /* assert */;
- (void 0) /* assert */;
- (void 0) /* assert */;
- const self = this;
- function onTransitionEnd() {
- // congrats! a successful transition completed!
- // ensure transition end events and timeouts have been cleared
- self._clearAsync();
- // ******** DOM WRITE ****************
- self._playEnd();
- // transition finished
- self._didFinishAll(shouldComplete, true, false);
- }
- function onTransitionFallback() {
- (void 0) /* console.debug */;
- // oh noz! the transition end event didn't fire in time!
- // instead the fallback timer when first
- // if all goes well this fallback should never fire
- // clear the other async end events from firing
- self._tm = undefined;
- self._clearAsync();
- // set the after styles
- // ******** DOM WRITE ****************
- self._playEnd(shouldComplete ? 1 : 0);
- // transition finished
- self._didFinishAll(shouldComplete, true, false);
- }
- // set the TRANSITION END event on one of the transition elements
- self._unrgTrns = this.plt.transitionEnd(self._transEl(), onTransitionEnd, false);
- // set a fallback timeout if the transition end event never fires, or is too slow
- // transition end fallback: (animation duration + XXms)
- self._tm = self.plt.timeout(onTransitionFallback, (dur + ANIMATION_TRANSITION_END_FALLBACK_PADDING_MS));
- }
- /**
- * @hidden
- * DOM WRITE
- * RECURSION
- */
- _playEnd(stepValue) {
- const children = this._c;
- for (let i = 0; i < this._cL; i++) {
- // ******** DOM WRITE ****************
- children[i]._playEnd(stepValue);
- }
- if (this._hasDur) {
- if (isDefined(stepValue)) {
- // too late to have a smooth animation, just finish it
- // ******** DOM WRITE ****************
- this._setTrans(0, true);
- // ensure the ending progress step gets rendered
- // ******** DOM WRITE ****************
- this._progress(stepValue);
- }
- // set the after styles
- // ******** DOM WRITE ****************
- this._setAfterStyles();
- // remove the will-change properties
- // ******** DOM WRITE ****************
- this._willChg(false);
- }
- }
- /**
- * @hidden
- * NO DOM
- * RECURSION
- */
- _hasDuration(opts) {
- if (this.getDuration(opts) > ANIMATION_DURATION_MIN) {
- return true;
- }
- const children = this._c;
- for (let i = 0; i < this._cL; i++) {
- if (children[i]._hasDuration(opts)) {
- return true;
- }
- }
- return false;
- }
- /**
- * @hidden
- * NO DOM
- * RECURSION
- */
- _hasDomReads() {
- if (this._rdFn && this._rdFn.length) {
- return true;
- }
- const children = this._c;
- for (let i = 0; i < this._cL; i++) {
- if (children[i]._hasDomReads()) {
- return true;
- }
- }
- return false;
- }
- /**
- * Immediately stop at the end of the animation.
- */
- stop(stepValue = 1) {
- // ensure all past transition end events have been cleared
- this._clearAsync();
- this._hasDur = true;
- this._playEnd(stepValue);
- }
- /**
- * @hidden
- * NO DOM
- * NO RECURSION
- */
- _clearAsync() {
- this._unrgTrns && this._unrgTrns();
- this._tm && clearTimeout(this._tm);
- this._tm = this._unrgTrns = undefined;
- }
- /**
- * @hidden
- * DOM WRITE
- * NO RECURSION
- */
- _progress(stepValue) {
- // bread 'n butter
- let val;
- let effects = this._fx;
- let nuElements = this._eL;
- if (!effects || !nuElements) {
- return;
- }
- // flip the number if we're going in reverse
- if (this._rv) {
- stepValue = ((stepValue * -1) + 1);
- }
- let i, j;
- let finalTransform = '';
- const elements = this._e;
- for (i = 0; i < effects.length; i++) {
- const fx = effects[i];
- if (fx.from && fx.to) {
- const fromNum = fx.from.num;
- const toNum = fx.to.num;
- const tweenEffect = (fromNum !== toNum);
- (void 0) /* assert */;
- if (tweenEffect) {
- this._twn = true;
- }
- if (stepValue === 0) {
- // FROM
- val = fx.from.val;
- }
- else if (stepValue === 1) {
- // TO
- val = fx.to.val;
- }
- else if (tweenEffect) {
- // EVERYTHING IN BETWEEN
- let valNum = (((toNum - fromNum) * stepValue) + fromNum);
- const unit = fx.to.unit;
- if (unit === 'px') {
- valNum = Math.round(valNum);
- }
- val = valNum + unit;
- }
- if (val !== null) {
- const prop = fx.name;
- if (fx.trans) {
- finalTransform += prop + '(' + val + ') ';
- }
- else {
- for (j = 0; j < nuElements; j++) {
- // ******** DOM WRITE ****************
- elements[j].style[prop] = val;
- }
- }
- }
- }
- }
- // place all transforms on the same property
- if (finalTransform.length) {
- if (!this._rv && stepValue !== 1 || this._rv && stepValue !== 0) {
- finalTransform += 'translateZ(0px)';
- }
- const cssTransform = this.plt.Css.transform;
- for (i = 0; i < elements.length; i++) {
- // ******** DOM WRITE ****************
- elements[i].style[cssTransform] = finalTransform;
- }
- }
- }
- /**
- * @hidden
- * DOM WRITE
- * NO RECURSION
- */
- _setTrans(dur, forcedLinearEasing) {
- // Transition is not enabled if there are not effects
- if (!this._fx) {
- return;
- }
- // set the TRANSITION properties inline on the element
- const elements = this._e;
- const easing = (forcedLinearEasing ? 'linear' : this.getEasing());
- const durString = dur + 'ms';
- const Css = this.plt.Css;
- const cssTransform = Css.transition;
- const cssTransitionDuration = Css.transitionDuration;
- const cssTransitionTimingFn = Css.transitionTimingFn;
- let eleStyle;
- for (let i = 0; i < this._eL; i++) {
- eleStyle = elements[i].style;
- if (dur > 0) {
- // ******** DOM WRITE ****************
- eleStyle[cssTransform] = '';
- eleStyle[cssTransitionDuration] = durString;
- // each animation can have a different easing
- if (easing) {
- // ******** DOM WRITE ****************
- eleStyle[cssTransitionTimingFn] = easing;
- }
- }
- else {
- eleStyle[cssTransform] = 'none';
- }
- }
- }
- /**
- * @hidden
- * DOM READ
- * DOM WRITE
- * RECURSION
- */
- _beforeAnimation() {
- // fire off all the "before" function that have DOM READS in them
- // elements will be in the DOM, however visibily hidden
- // so we can read their dimensions if need be
- // ******** DOM READ ****************
- this._fireBeforeReadFunc();
- // ******** DOM READS ABOVE / DOM WRITES BELOW ****************
- // fire off all the "before" function that have DOM WRITES in them
- // ******** DOM WRITE ****************
- this._fireBeforeWriteFunc();
- // stage all of the before css classes and inline styles
- // ******** DOM WRITE ****************
- this._setBeforeStyles();
- }
- /**
- * @hidden
- * DOM WRITE
- * RECURSION
- */
- _setBeforeStyles() {
- let i, j;
- const children = this._c;
- for (i = 0; i < this._cL; i++) {
- children[i]._setBeforeStyles();
- }
- // before the animations have started
- // only set before styles if animation is not reversed
- if (this._rv) {
- return;
- }
- const addClasses = this._bfAdd;
- const removeClasses = this._bfRm;
- let ele;
- let eleClassList;
- let prop;
- for (i = 0; i < this._eL; i++) {
- ele = this._e[i];
- eleClassList = ele.classList;
- // css classes to add before the animation
- if (addClasses) {
- for (j = 0; j < addClasses.length; j++) {
- // ******** DOM WRITE ****************
- eleClassList.add(addClasses[j]);
- }
- }
- // css classes to remove before the animation
- if (removeClasses) {
- for (j = 0; j < removeClasses.length; j++) {
- // ******** DOM WRITE ****************
- eleClassList.remove(removeClasses[j]);
- }
- }
- // inline styles to add before the animation
- if (this._bfSty) {
- for (prop in this._bfSty) {
- // ******** DOM WRITE ****************
- ele.style[prop] = this._bfSty[prop];
- }
- }
- }
- }
- /**
- * @hidden
- * DOM READ
- * RECURSION
- */
- _fireBeforeReadFunc() {
- const children = this._c;
- for (let i = 0; i < this._cL; i++) {
- // ******** DOM READ ****************
- children[i]._fireBeforeReadFunc();
- }
- const readFunctions = this._rdFn;
- if (readFunctions) {
- for (let i = 0; i < readFunctions.length; i++) {
- // ******** DOM READ ****************
- readFunctions[i]();
- }
- }
- }
- /**
- * @hidden
- * DOM WRITE
- * RECURSION
- */
- _fireBeforeWriteFunc() {
- const children = this._c;
- for (let i = 0; i < this._cL; i++) {
- // ******** DOM WRITE ****************
- children[i]._fireBeforeWriteFunc();
- }
- const writeFunctions = this._wrFn;
- if (this._wrFn) {
- for (let i = 0; i < writeFunctions.length; i++) {
- // ******** DOM WRITE ****************
- writeFunctions[i]();
- }
- }
- }
- /**
- * @hidden
- * DOM WRITE
- */
- _setAfterStyles() {
- let i, j;
- let ele;
- let eleClassList;
- let elements = this._e;
- for (i = 0; i < this._eL; i++) {
- ele = elements[i];
- eleClassList = ele.classList;
- // remove the transition duration/easing
- // ******** DOM WRITE ****************
- ele.style[this.plt.Css.transitionDuration] = ele.style[this.plt.Css.transitionTimingFn] = '';
- if (this._rv) {
- // finished in reverse direction
- // css classes that were added before the animation should be removed
- if (this._bfAdd) {
- for (j = 0; j < this._bfAdd.length; j++) {
- // ******** DOM WRITE ****************
- eleClassList.remove(this._bfAdd[j]);
- }
- }
- // css classes that were removed before the animation should be added
- if (this._bfRm) {
- for (j = 0; j < this._bfRm.length; j++) {
- // ******** DOM WRITE ****************
- eleClassList.add(this._bfRm[j]);
- }
- }
- // inline styles that were added before the animation should be removed
- if (this._bfSty) {
- for (const prop in this._bfSty) {
- // ******** DOM WRITE ****************
- ele.style[prop] = '';
- }
- }
- }
- else {
- // finished in forward direction
- // css classes to add after the animation
- if (this._afAdd) {
- for (j = 0; j < this._afAdd.length; j++) {
- // ******** DOM WRITE ****************
- eleClassList.add(this._afAdd[j]);
- }
- }
- // css classes to remove after the animation
- if (this._afRm) {
- for (j = 0; j < this._afRm.length; j++) {
- // ******** DOM WRITE ****************
- eleClassList.remove(this._afRm[j]);
- }
- }
- // inline styles to add after the animation
- if (this._afSty) {
- for (const prop in this._afSty) {
- // ******** DOM WRITE ****************
- ele.style[prop] = this._afSty[prop];
- }
- }
- }
- }
- }
- /**
- * @hidden
- * DOM WRITE
- * NO RECURSION
- */
- _willChg(addWillChange) {
- let wc;
- let effects = this._fx;
- let willChange;
- if (addWillChange && effects) {
- wc = [];
- for (let i = 0; i < effects.length; i++) {
- const propWC = effects[i].wc;
- if (propWC === 'webkitTransform') {
- wc.push('transform', '-webkit-transform');
- }
- else {
- wc.push(propWC);
- }
- }
- willChange = wc.join(',');
- }
- else {
- willChange = '';
- }
- for (let i = 0; i < this._eL; i++) {
- // ******** DOM WRITE ****************
- this._e[i].style.willChange = willChange;
- }
- }
- /**
- * Start the animation with a user controlled progress.
- */
- progressStart() {
- // ensure all past transition end events have been cleared
- this._clearAsync();
- // ******** DOM READ/WRITE ****************
- this._beforeAnimation();
- // ******** DOM WRITE ****************
- this._progressStart();
- }
- /**
- * @hidden
- * DOM WRITE
- * RECURSION
- */
- _progressStart() {
- const children = this._c;
- for (let i = 0; i < this._cL; i++) {
- // ******** DOM WRITE ****************
- children[i]._progressStart();
- }
- // force no duration, linear easing
- // ******** DOM WRITE ****************
- this._setTrans(0, true);
- // ******** DOM WRITE ****************
- this._willChg(true);
- }
- /**
- * Set the progress step for this animation.
- * progressStep() is not debounced, so it should not be called faster than 60FPS.
- */
- progressStep(stepValue) {
- // only update if the last update was more than 16ms ago
- stepValue = Math.min(1, Math.max(0, stepValue));
- const children = this._c;
- for (let i = 0; i < this._cL; i++) {
- // ******** DOM WRITE ****************
- children[i].progressStep(stepValue);
- }
- if (this._rv) {
- // if the animation is going in reverse then
- // flip the step value: 0 becomes 1, 1 becomes 0
- stepValue = ((stepValue * -1) + 1);
- }
- // ******** DOM WRITE ****************
- this._progress(stepValue);
- }
- /**
- * End the progress animation.
- */
- progressEnd(shouldComplete, currentStepValue, dur = -1) {
- (void 0) /* console.debug */;
- if (this._rv) {
- // if the animation is going in reverse then
- // flip the step value: 0 becomes 1, 1 becomes 0
- currentStepValue = ((currentStepValue * -1) + 1);
- }
- const stepValue = shouldComplete ? 1 : 0;
- const diff = Math.abs(currentStepValue - stepValue);
- if (diff < 0.05) {
- dur = 0;
- }
- else if (dur < 0) {
- dur = this._dur;
- }
- this._isAsync = (dur > 30);
- this._progressEnd(shouldComplete, stepValue, dur, this._isAsync);
- if (this._isAsync) {
- // for the root animation only
- // set the async TRANSITION END event
- // and run onFinishes when the transition ends
- // ******** DOM WRITE ****************
- this._asyncEnd(dur, shouldComplete);
- // this animation has a duration so we need another RAF
- // for the CSS TRANSITION properties to kick in
- this.plt && this.plt.raf(this._playToStep.bind(this, stepValue));
- }
- }
- /**
- * @hidden
- * DOM WRITE
- * RECURSION
- */
- _progressEnd(shouldComplete, stepValue, dur, isAsync) {
- const children = this._c;
- for (let i = 0; i < this._cL; i++) {
- // ******** DOM WRITE ****************
- children[i]._progressEnd(shouldComplete, stepValue, dur, isAsync);
- }
- if (!isAsync) {
- // stop immediately
- // set all the animations to their final position
- // ******** DOM WRITE ****************
- this._progress(stepValue);
- this._willChg(false);
- this._setAfterStyles();
- this._didFinish(shouldComplete);
- }
- else {
- // animate it back to it's ending position
- this.isPlaying = true;
- this.hasCompleted = false;
- this._hasDur = true;
- // ******** DOM WRITE ****************
- this._willChg(true);
- this._setTrans(dur, false);
- }
- }
- /**
- * Add a callback to fire when the animation has finished.
- */
- onFinish(callback, onceTimeCallback = false, clearOnFinishCallacks = false) {
- if (clearOnFinishCallacks) {
- this._fFn = this._fOneFn = undefined;
- }
- if (onceTimeCallback) {
- this._fOneFn = this._fOneFn || [];
- this._fOneFn.push(callback);
- }
- else {
- this._fFn = this._fFn || [];
- this._fFn.push(callback);
- }
- return this;
- }
- /**
- * @hidden
- * NO DOM
- * RECURSION
- */
- _didFinishAll(hasCompleted, finishAsyncAnimations, finishNoDurationAnimations) {
- const children = this._c;
- for (let i = 0; i < this._cL; i++) {
- children[i]._didFinishAll(hasCompleted, finishAsyncAnimations, finishNoDurationAnimations);
- }
- if (finishAsyncAnimations && this._isAsync || finishNoDurationAnimations && !this._isAsync) {
- this._didFinish(hasCompleted);
- }
- }
- /**
- * @hidden
- * NO RECURSION
- */
- _didFinish(hasCompleted) {
- this.isPlaying = false;
- this.hasCompleted = hasCompleted;
- if (this._fFn) {
- // run all finish callbacks
- for (let i = 0; i < this._fFn.length; i++) {
- this._fFn[i](this);
- }
- }
- if (this._fOneFn) {
- // run all "onetime" finish callbacks
- for (let i = 0; i < this._fOneFn.length; i++) {
- this._fOneFn[i](this);
- }
- this._fOneFn.length = 0;
- }
- }
- /**
- * Reverse the animation.
- */
- reverse(shouldReverse = true) {
- const children = this._c;
- for (let i = 0; i < this._cL; i++) {
- children[i].reverse(shouldReverse);
- }
- this._rv = shouldReverse;
- return this;
- }
- /**
- * Recursively destroy this animation and all child animations.
- */
- destroy() {
- const children = this._c;
- for (let i = 0; i < this._cL; i++) {
- children[i].destroy();
- }
- this._clearAsync();
- this.parent = this.plt = this._e = this._rdFn = this._wrFn = null;
- if (this._c) {
- this._c.length = this._cL = 0;
- }
- if (this._fFn) {
- this._fFn.length = 0;
- }
- if (this._fOneFn) {
- this._fOneFn.length = 0;
- }
- }
- /**
- * @hidden
- * NO DOM
- */
- _transEl() {
- // get the lowest level element that has an Animation
- let targetEl;
- for (let i = 0; i < this._cL; i++) {
- targetEl = this._c[i]._transEl();
- if (targetEl) {
- return targetEl;
- }
- }
- return (this._twn && this._hasDur && this._eL ? this._e[0] : null);
- }
- }
- const ANIMATION_TRANSFORMS = {
- 'translateX': 1,
- 'translateY': 1,
- 'translateZ': 1,
- 'scale': 1,
- 'scaleX': 1,
- 'scaleY': 1,
- 'scaleZ': 1,
- 'rotate': 1,
- 'rotateX': 1,
- 'rotateY': 1,
- 'rotateZ': 1,
- 'skewX': 1,
- 'skewY': 1,
- 'perspective': 1
- };
- const ANIMATION_CSS_VALUE_REGEX = /(^-?\d*\.?\d*)(.*)/;
- const ANIMATION_DURATION_MIN = 32;
- const ANIMATION_TRANSITION_END_FALLBACK_PADDING_MS = 400;
- //# sourceMappingURL=animation.js.map
|