refactor(animation): strict ts

This commit is contained in:
Manu Mtz.-Almeida
2018-04-02 17:52:35 +02:00
parent 7aa5d059ad
commit af240a9ffa

View File

@ -27,30 +27,28 @@ const raf = window.requestAnimationFrame || ((f: Function) => f());
export class Animator { export class Animator {
private _afterAddClasses: string[]; private _afterAddClasses: string[] | undefined;
private _afterRemoveClasses: string[]; private _afterRemoveClasses: string[] | undefined;
private _afterStyles: { [property: string]: any; }; private _afterStyles: { [property: string]: any; } | undefined;
private _beforeAddClasses: string[]; private _beforeAddClasses: string[] | undefined;
private _beforeRemoveClasses: string[]; private _beforeRemoveClasses: string[] | undefined;
private _beforeStyles: { [property: string]: any; }; private _beforeStyles: { [property: string]: any; } | undefined;
private _childAnimations: Animator[]; private _childAnimations: Animator[] | undefined;
private _childAnimationTotal: number; private _duration: number | undefined;
private _duration: number|null = null; private _easingName: string | undefined;
private _easingName: string|null = null; private _elements: HTMLElement[] | undefined;
private _elements: HTMLElement[]|null = null; private _fxProperties: EffectProperty[] | undefined;
private _elementTotal: number; private _hasDur = false;
private _fxProperties: EffectProperty[]; private _hasTweenEffect = false;
private _hasDur: boolean; private _isAsync = false;
private _hasTweenEffect: boolean; private _isReverse = false;
private _isAsync: boolean;
private _isReverse: boolean;
private _onFinishCallbacks: Function[] | undefined; private _onFinishCallbacks: Function[] | undefined;
private _onFinishOneTimeCallbacks: Function[] | undefined; private _onFinishOneTimeCallbacks: Function[] | undefined;
private _readCallbacks: Function[]; private _readCallbacks: Function[] | undefined;
private _reversedEasingName: string|undefined; private _reversedEasingName: string | undefined;
private _timerId: any; private _timerId: any | undefined;
private _unregisterTrnsEnd: Function | undefined; private _unregisterTrnsEnd: Function | undefined;
private _writeCallbacks: Function[]; private _writeCallbacks: Function[] | undefined;
private _destroyed = false; private _destroyed = false;
parent: Animator|undefined; parent: Animator|undefined;
@ -77,7 +75,7 @@ export class Animator {
*/ */
private _addEl(el: any) { private _addEl(el: any) {
if (el.nodeType === 1) { if (el.nodeType === 1) {
this._elementTotal = (this._elements = this._elements || []).push(el); (this._elements = this._elements || []).push(el);
} }
} }
@ -87,7 +85,7 @@ export class Animator {
add(childAnimation: Animator): Animator { add(childAnimation: Animator): Animator {
childAnimation.parent = this; childAnimation.parent = this;
this.hasChildren = true; this.hasChildren = true;
this._childAnimationTotal = (this._childAnimations = this._childAnimations || []).push(childAnimation); (this._childAnimations = this._childAnimations || []).push(childAnimation);
return this; return this;
} }
@ -96,9 +94,9 @@ export class Animator {
* not have a duration, then it'll get the duration from its parent. * not have a duration, then it'll get the duration from its parent.
*/ */
getDuration(opts?: PlayOptions): number { getDuration(opts?: PlayOptions): number {
if (opts && opts.duration !== null && opts.duration !== undefined) { if (opts && opts.duration != null) {
return opts.duration; return opts.duration;
} else if (this._duration !== null) { } else if (this._duration != null) {
return this._duration; return this._duration;
} else if (this.parent) { } else if (this.parent) {
return this.parent.getDuration(); return this.parent.getDuration();
@ -129,7 +127,7 @@ export class Animator {
if (this._isReverse && this._reversedEasingName) { if (this._isReverse && this._reversedEasingName) {
return this._reversedEasingName; return this._reversedEasingName;
} }
return this._easingName !== null ? this._easingName : (this.parent && this.parent.getEasing()) || null; return this._easingName != null ? this._easingName : (this.parent && this.parent.getEasing()) || null;
} }
/** /**
@ -185,9 +183,6 @@ export class Animator {
private _getProp(name: string): EffectProperty | undefined { private _getProp(name: string): EffectProperty | undefined {
if (this._fxProperties) { if (this._fxProperties) {
return this._fxProperties.find(prop => prop.effectName === name); return this._fxProperties.find(prop => prop.effectName === name);
} else {
this._fxProperties = [];
} }
return undefined; return undefined;
} }
@ -205,7 +200,7 @@ export class Animator {
// add the will-change property for transforms or opacity // add the will-change property for transforms or opacity
wc: (shouldTrans ? CSS_PROP.transformProp : prop) wc: (shouldTrans ? CSS_PROP.transformProp : prop)
} as EffectProperty; } as EffectProperty;
this._fxProperties.push(fxProp); (this._fxProperties = this._fxProperties || []).push(fxProp);
} }
// add from/to EffectState to the EffectProperty // add from/to EffectState to the EffectProperty
@ -409,9 +404,11 @@ export class Animator {
this._hasDur = (this.getDuration(opts) > DURATION_MIN); this._hasDur = (this.getDuration(opts) > DURATION_MIN);
const children = this._childAnimations; const children = this._childAnimations;
for (let i = 0; i < this._childAnimationTotal; i++) { if (children) {
// ******** DOM WRITE **************** for (let i = 0; i < children.length; i++) {
children[i]._playInit(opts); // ******** DOM WRITE ****************
children[i]._playInit(opts);
}
} }
if (this._hasDur) { if (this._hasDur) {
@ -465,9 +462,11 @@ export class Animator {
*/ */
_playProgress(opts: PlayOptions|undefined) { _playProgress(opts: PlayOptions|undefined) {
const children = this._childAnimations; const children = this._childAnimations;
for (let i = 0; i < this._childAnimationTotal; i++) { if (children) {
// ******** DOM WRITE **************** for (let i = 0; i < children.length; i++) {
children[i]._playProgress(opts); // ******** DOM WRITE ****************
children[i]._playProgress(opts);
}
} }
if (this._hasDur) { if (this._hasDur) {
@ -498,9 +497,11 @@ export class Animator {
_playToStep(stepValue: number) { _playToStep(stepValue: number) {
if (!this._destroyed) { if (!this._destroyed) {
const children = this._childAnimations; const children = this._childAnimations;
for (let i = 0; i < this._childAnimationTotal; i++) { if (children) {
// ******** DOM WRITE **************** for (let i = 0; i < children.length; i++) {
children[i]._playToStep(stepValue); // ******** DOM WRITE ****************
children[i]._playToStep(stepValue);
}
} }
if (this._hasDur) { if (this._hasDur) {
@ -565,9 +566,11 @@ export class Animator {
*/ */
_playEnd(stepValue?: number) { _playEnd(stepValue?: number) {
const children = this._childAnimations; const children = this._childAnimations;
for (let i = 0; i < this._childAnimationTotal; i++) { if (children) {
// ******** DOM WRITE **************** for (let i = 0; i < children.length; i++) {
children[i]._playEnd(stepValue); // ******** DOM WRITE ****************
children[i]._playEnd(stepValue);
}
} }
if (this._hasDur) { if (this._hasDur) {
@ -601,9 +604,11 @@ export class Animator {
} }
const children = this._childAnimations; const children = this._childAnimations;
for (let i = 0; i < this._childAnimationTotal; i++) { if (children) {
if (children[i]._hasDuration(opts)) { for (let i = 0; i < children.length; i++) {
return true; if (children[i]._hasDuration(opts)) {
return true;
}
} }
} }
return false; return false;
@ -619,9 +624,11 @@ export class Animator {
} }
const children = this._childAnimations; const children = this._childAnimations;
for (let i = 0; i < this._childAnimationTotal; i++) { if (children) {
if (children[i]._hasDomReads()) { for (let i = 0; i < children.length; i++) {
return true; if (children[i]._hasDomReads()) {
return true;
}
} }
} }
return false; return false;
@ -659,9 +666,8 @@ export class Animator {
let val: any; let val: any;
const elements = this._elements; const elements = this._elements;
const effects = this._fxProperties; const effects = this._fxProperties;
const nuElements = this._elementTotal;
if (!elements || !effects || !nuElements || this._destroyed) { if (!elements || elements.length === 0 || !effects || this._destroyed) {
return; return;
} }
@ -710,7 +716,7 @@ export class Animator {
finalTransform += prop + '(' + val + ') '; finalTransform += prop + '(' + val + ') ';
} else { } else {
for (j = 0; j < nuElements; j++) { for (j = 0; j < elements.length; j++) {
// ******** DOM WRITE **************** // ******** DOM WRITE ****************
(elements[j].style as any)[prop] = val; (elements[j].style as any)[prop] = val;
} }
@ -739,8 +745,7 @@ export class Animator {
_setTrans(dur: number, forcedLinearEasing: boolean) { _setTrans(dur: number, forcedLinearEasing: boolean) {
// Transition is not enabled if there are not effects // Transition is not enabled if there are not effects
const elements = this._elements; const elements = this._elements;
const nuElements = this._elementTotal; if (!elements || elements.length === 0 || !this._fxProperties) {
if (!elements || !this._fxProperties || nuElements === 0) {
return; return;
} }
@ -752,7 +757,7 @@ export class Animator {
const cssTransitionTimingFn = CSS_PROP.transitionTimingFnProp; const cssTransitionTimingFn = CSS_PROP.transitionTimingFnProp;
let eleStyle: any; let eleStyle: any;
for (let i = 0; i < nuElements; i++) { for (let i = 0; i < elements.length; i++) {
eleStyle = elements[i].style; eleStyle = elements[i].style;
if (dur > 0) { if (dur > 0) {
// ******** DOM WRITE **************** // ******** DOM WRITE ****************
@ -798,31 +803,30 @@ export class Animator {
* RECURSION * RECURSION
*/ */
_setBeforeStyles() { _setBeforeStyles() {
let j: number;
const children = this._childAnimations; const children = this._childAnimations;
if (children) {
for (let i = 0; i < this._childAnimationTotal; i++) { for (let i = 0; i < children.length; i++) {
children[i]._setBeforeStyles(); children[i]._setBeforeStyles();
}
} }
const elements = this._elements; const elements = this._elements;
const nuElements = this._elementTotal;
// before the animations have started // before the animations have started
// only set before styles if animation is not reversed // only set before styles if animation is not reversed
if (!elements || nuElements === 0 || this._isReverse) { if (!elements || elements.length === 0 || this._isReverse) {
return; return;
} }
const addClasses = this._beforeAddClasses; const addClasses = this._beforeAddClasses;
const removeClasses = this._beforeRemoveClasses; const removeClasses = this._beforeRemoveClasses;
let prop: string; let prop: string;
for (let i = 0; i < nuElements; i++) { for (let i = 0; i < elements.length; i++) {
const el = elements[i]; const el = elements[i];
const elementClassList = el.classList; const elementClassList = el.classList;
// css classes to add before the animation // css classes to add before the animation
if (addClasses) { if (addClasses) {
for (j = 0; j < addClasses.length; j++) { for (let j = 0; j < addClasses.length; j++) {
// ******** DOM WRITE **************** // ******** DOM WRITE ****************
elementClassList.add(addClasses[j]); elementClassList.add(addClasses[j]);
} }
@ -830,7 +834,7 @@ export class Animator {
// css classes to remove before the animation // css classes to remove before the animation
if (removeClasses) { if (removeClasses) {
for (j = 0; j < removeClasses.length; j++) { for (let j = 0; j < removeClasses.length; j++) {
// ******** DOM WRITE **************** // ******** DOM WRITE ****************
elementClassList.remove(removeClasses[j]); elementClassList.remove(removeClasses[j]);
} }
@ -852,16 +856,16 @@ export class Animator {
*/ */
_fireBeforeReadFunc() { _fireBeforeReadFunc() {
const children = this._childAnimations; const children = this._childAnimations;
let i = 0; if (children) {
for (let i = 0; i < children.length; i++) {
for (i = 0; i < this._childAnimationTotal; i++) { // ******** DOM READ ****************
// ******** DOM READ **************** children[i]._fireBeforeReadFunc();
children[i]._fireBeforeReadFunc(); }
} }
const readFunctions = this._readCallbacks; const readFunctions = this._readCallbacks;
if (readFunctions) { if (readFunctions) {
for (i = 0; i < readFunctions.length; i++) { for (let i = 0; i < readFunctions.length; i++) {
// ******** DOM READ **************** // ******** DOM READ ****************
readFunctions[i](); readFunctions[i]();
} }
@ -874,16 +878,16 @@ export class Animator {
*/ */
_fireBeforeWriteFunc() { _fireBeforeWriteFunc() {
const children = this._childAnimations; const children = this._childAnimations;
let i = 0; if (children) {
for (let i = 0; i < children.length; i++) {
for (i = 0; i < this._childAnimationTotal; i++) { // ******** DOM WRITE ****************
// ******** DOM WRITE **************** children[i]._fireBeforeWriteFunc();
children[i]._fireBeforeWriteFunc(); }
} }
const writeFunctions = this._writeCallbacks; const writeFunctions = this._writeCallbacks;
if (this._writeCallbacks) { if (writeFunctions) {
for (i = 0; i < writeFunctions.length; i++) { for (let i = 0; i < writeFunctions.length; i++) {
// ******** DOM WRITE **************** // ******** DOM WRITE ****************
writeFunctions[i](); writeFunctions[i]();
} }
@ -903,7 +907,7 @@ export class Animator {
} }
let prop: string; let prop: string;
for (i = 0; i < this._elementTotal; i++) { for (i = 0; i < elements.length; i++) {
el = elements[i]; el = elements[i];
elementClassList = el.classList; elementClassList = el.classList;
@ -996,7 +1000,7 @@ export class Animator {
const elements = this._elements; const elements = this._elements;
if (elements) { if (elements) {
for (let i = 0; i < this._elementTotal; i++) { for (let i = 0; i < elements.length; i++) {
// ******** DOM WRITE **************** // ******** DOM WRITE ****************
(elements[i] as any).style.willChange = willChange; (elements[i] as any).style.willChange = willChange;
} }
@ -1023,9 +1027,11 @@ export class Animator {
*/ */
_progressStart() { _progressStart() {
const children = this._childAnimations; const children = this._childAnimations;
for (let i = 0; i < this._childAnimationTotal; i++) { if (children) {
// ******** DOM WRITE **************** for (let i = 0; i < children.length; i++) {
children[i]._progressStart(); // ******** DOM WRITE ****************
children[i]._progressStart();
}
} }
// force no duration, linear easing // force no duration, linear easing
@ -1044,9 +1050,11 @@ export class Animator {
stepValue = Math.min(1, Math.max(0, stepValue)); stepValue = Math.min(1, Math.max(0, stepValue));
const children = this._childAnimations; const children = this._childAnimations;
for (let i = 0; i < this._childAnimationTotal; i++) { if (children) {
// ******** DOM WRITE **************** for (let i = 0; i < children.length; i++) {
children[i].progressStep(stepValue); // ******** DOM WRITE ****************
children[i].progressStep(stepValue);
}
} }
// ******** DOM WRITE **************** // ******** DOM WRITE ****************
@ -1063,7 +1071,6 @@ export class Animator {
currentStepValue = 1 - currentStepValue; currentStepValue = 1 - currentStepValue;
} }
const stepValue = shouldComplete ? 1 : 0; const stepValue = shouldComplete ? 1 : 0;
const diff = Math.abs(currentStepValue - stepValue); const diff = Math.abs(currentStepValue - stepValue);
if (dur === undefined) { if (dur === undefined) {
dur = -1; dur = -1;
@ -1101,9 +1108,11 @@ export class Animator {
*/ */
_progressEnd(shouldComplete: boolean, stepValue: number, dur: number, isAsync: boolean) { _progressEnd(shouldComplete: boolean, stepValue: number, dur: number, isAsync: boolean) {
const children = this._childAnimations; const children = this._childAnimations;
for (let i = 0; i < this._childAnimationTotal; i++) { if (children) {
// ******** DOM WRITE **************** for (let i = 0; i < children.length; i++) {
children[i]._progressEnd(shouldComplete, stepValue, dur, isAsync); // ******** DOM WRITE ****************
children[i]._progressEnd(shouldComplete, stepValue, dur, isAsync);
}
} }
if (!isAsync) { if (!isAsync) {
@ -1151,8 +1160,10 @@ export class Animator {
*/ */
_didFinishAll(hasCompleted: boolean, finishAsyncAnimations: boolean, finishNoDurationAnimations: boolean) { _didFinishAll(hasCompleted: boolean, finishAsyncAnimations: boolean, finishNoDurationAnimations: boolean) {
const children = this._childAnimations; const children = this._childAnimations;
for (let i = 0; i < this._childAnimationTotal; i++) { if (children) {
children[i]._didFinishAll(hasCompleted, finishAsyncAnimations, finishNoDurationAnimations); for (let i = 0; i < children.length; i++) {
children[i]._didFinishAll(hasCompleted, finishAsyncAnimations, finishNoDurationAnimations);
}
} }
if (finishAsyncAnimations && this._isAsync || finishNoDurationAnimations && !this._isAsync) { if (finishAsyncAnimations && this._isAsync || finishNoDurationAnimations && !this._isAsync) {
@ -1166,18 +1177,17 @@ export class Animator {
_didFinish(hasCompleted: boolean) { _didFinish(hasCompleted: boolean) {
this.isPlaying = false; this.isPlaying = false;
this.hasCompleted = hasCompleted; this.hasCompleted = hasCompleted;
let i = 0;
if (this._onFinishCallbacks) { if (this._onFinishCallbacks) {
// run all finish callbacks // run all finish callbacks
for (i = 0; i < this._onFinishCallbacks.length; i++) { for (let i = 0; i < this._onFinishCallbacks.length; i++) {
this._onFinishCallbacks[i](this); this._onFinishCallbacks[i](this);
} }
} }
if (this._onFinishOneTimeCallbacks) { if (this._onFinishOneTimeCallbacks) {
// run all "onetime" finish callbacks // run all "onetime" finish callbacks
for (i = 0; i < this._onFinishOneTimeCallbacks.length; i++) { for (let i = 0; i < this._onFinishOneTimeCallbacks.length; i++) {
this._onFinishOneTimeCallbacks[i](this); this._onFinishOneTimeCallbacks[i](this);
} }
this._onFinishOneTimeCallbacks.length = 0; this._onFinishOneTimeCallbacks.length = 0;
@ -1192,10 +1202,12 @@ export class Animator {
shouldReverse = true; shouldReverse = true;
} }
const children = this._childAnimations; const children = this._childAnimations;
for (let i = 0; i < this._childAnimationTotal; i++) { if (children) {
children[i].reverse(shouldReverse); for (let i = 0; i < children.length; i++) {
children[i].reverse(shouldReverse);
}
} }
this._isReverse = shouldReverse; this._isReverse = !!shouldReverse;
return this; return this;
} }
@ -1206,14 +1218,16 @@ export class Animator {
this._destroyed = true; this._destroyed = true;
const children = this._childAnimations; const children = this._childAnimations;
for (let i = 0; i < this._childAnimationTotal; i++) { if (children) {
children[i].destroy(); for (let i = 0; i < children.length; i++) {
children[i].destroy();
}
} }
this._clearAsync(); this._clearAsync();
if (this._elements) { if (this._elements) {
this._elements.length = this._elementTotal = 0; this._elements.length = 0;
} }
if (this._readCallbacks) { if (this._readCallbacks) {
@ -1227,7 +1241,7 @@ export class Animator {
this.parent = undefined; this.parent = undefined;
if (this._childAnimations) { if (this._childAnimations) {
this._childAnimations.length = this._childAnimationTotal = 0; this._childAnimations.length = 0;
} }
if (this._onFinishCallbacks) { if (this._onFinishCallbacks) {
this._onFinishCallbacks.length = 0; this._onFinishCallbacks.length = 0;
@ -1242,13 +1256,21 @@ export class Animator {
*/ */
_transEl(): HTMLElement|null { _transEl(): HTMLElement|null {
// get the lowest level element that has an Animator // get the lowest level element that has an Animator
for (let i = 0; i < this._childAnimationTotal; i++) { const children = this._childAnimations;
const targetEl = this._childAnimations[i]._transEl(); if (children) {
if (targetEl) { for (let i = 0; i < children.length; i++) {
return targetEl; const targetEl = children[i]._transEl();
if (targetEl) {
return targetEl;
}
} }
} }
return (this._hasTweenEffect && this._hasDur && this._elements && this._elementTotal > 0 ? this._elements[0] : null); return (
this._hasTweenEffect &&
this._hasDur &&
this._elements &&
this._elements.length > 0 ?
this._elements[0] : null);
} }
} }