perf(animation): reduce flickering when updating css animation on lower end devices (#19138)

* fix flickering on lower end devices

* fix flickering, reduce timeout padding

* Add raf for clean up

* bug fix

* ensure animations are cleaned up

* Revert "ensure animations are cleaned up"

Thie reverts commit cf363f00be5567ba346d68659211087c8848d0d4.

* fix dependnecy

* Revert "ensure animations are cleaned up"
merge
This reverts commit cf363f00be5567ba346d68659211087c8848d0d4.
This commit is contained in:
Liam DeBeasi
2019-08-20 19:03:17 -04:00
committed by GitHub
parent 67ed89ded8
commit 45a59d13cc
2 changed files with 48 additions and 37 deletions

View File

@ -415,7 +415,7 @@ export class Menu implements ComponentInterface, MenuI {
let realDur = 0; let realDur = 0;
if (missingDistance > 5) { if (missingDistance > 5) {
const dur = missingDistance / Math.abs(velocity); const dur = missingDistance / Math.abs(velocity);
realDur = Math.min(dur, 300); realDur = Math.max(dur, 300);
} }
this.lastOnEnd = detail.timeStamp; this.lastOnEnd = detail.timeStamp;

View File

@ -43,7 +43,7 @@ export const createAnimation = () => {
const _afterAddWriteFunctions: any[] = []; const _afterAddWriteFunctions: any[] = [];
const webAnimations: any[] = []; const webAnimations: any[] = [];
const supportsWebAnimations = (typeof (window as any).Animation === 'function'); const supportsWebAnimations = (typeof (window as any).Animation === 'function');
const ANIMATION_END_FALLBACK_PADDING_MS = 400; const ANIMATION_END_FALLBACK_PADDING_MS = 100;
/** /**
* Returns the raw Web Animations object * Returns the raw Web Animations object
@ -713,26 +713,28 @@ export const createAnimation = () => {
const updateCSSAnimation = (toggleAnimationName = true) => { const updateCSSAnimation = (toggleAnimationName = true) => {
elements.forEach(element => { elements.forEach(element => {
setStyleProperty(element, 'animation-name', keyframeName || null);
setStyleProperty(element, 'animation-duration', (getDuration() !== undefined) ? `${getDuration()}ms` : null);
setStyleProperty(element, 'animation-timing-function', getEasing() || null);
setStyleProperty(element, 'animation-delay', (getDelay() !== undefined) ? `${getDelay()}ms` : null);
setStyleProperty(element, 'animation-fill-mode', getFill() || null);
setStyleProperty(element, 'animation-direction', getDirection() || null);
const iterationsCount =
(getIterations() !== undefined) ?
(getIterations() === Infinity) ? 'infinite' : getIterations()!.toString()
: null;
setStyleProperty(element, 'animation-iteration-count', iterationsCount);
if (toggleAnimationName) {
setStyleProperty(element, 'animation-name', `${keyframeName}-alt`);
}
requestAnimationFrame(() => { requestAnimationFrame(() => {
setStyleProperty(element, 'animation-name', keyframeName || null); setStyleProperty(element, 'animation-name', keyframeName || null);
setStyleProperty(element, 'animation-duration', (getDuration() !== undefined) ? `${getDuration()}ms` : null);
setStyleProperty(element, 'animation-timing-function', getEasing() || null);
setStyleProperty(element, 'animation-delay', (getDelay() !== undefined) ? `${getDelay()}ms` : null);
setStyleProperty(element, 'animation-fill-mode', getFill() || null);
setStyleProperty(element, 'animation-direction', getDirection() || null);
const iterationsCount =
(getIterations() !== undefined) ?
(getIterations() === Infinity) ? 'infinite' : getIterations()!.toString()
: null;
setStyleProperty(element, 'animation-iteration-count', iterationsCount);
if (toggleAnimationName) {
setStyleProperty(element, 'animation-name', `${keyframeName}-alt`);
}
requestAnimationFrame(() => {
setStyleProperty(element, 'animation-name', keyframeName || null);
});
}); });
}); });
}; };
@ -905,7 +907,9 @@ export const createAnimation = () => {
elements.forEach(element => { elements.forEach(element => {
if (_keyframes.length > 0) { if (_keyframes.length > 0) {
setStyleProperty(element, 'animation-play-state', 'running'); requestAnimationFrame(() => {
setStyleProperty(element, 'animation-play-state', 'running');
});
} }
}); });
@ -927,19 +931,33 @@ export const createAnimation = () => {
animationEnd(elements[0], () => { animationEnd(elements[0], () => {
clearCSSAnimationsTimeout(); clearCSSAnimationsTimeout();
clearCSSAnimationPlayState();
animationFinish(); /**
* Ensure that clean up
* is always done a frame
* before the onFinish handlers
* are fired. Otherwise, there
* may be flickering if a new
* animation is started on the same
* element too quickly
*
* TODO: Is there a cleaner way to do this?
*/
requestAnimationFrame(() => {
clearCSSAnimationPlayState();
requestAnimationFrame(() => {
animationFinish();
});
});
}); });
} }
}; };
const clearCSSAnimationPlayState = () => { const clearCSSAnimationPlayState = () => {
elements.forEach(element => { elements.forEach(element => {
requestAnimationFrame(() => { removeStyleProperty(element, 'animation-duration');
removeStyleProperty(element, 'animation-duration'); removeStyleProperty(element, 'animation-delay');
removeStyleProperty(element, 'animation-delay'); removeStyleProperty(element, 'animation-play-state');
removeStyleProperty(element, 'animation-play-state');
});
}); });
}; };
@ -953,18 +971,11 @@ export const createAnimation = () => {
} }
}; };
const resetCSSAnimations = () => {
elements.forEach(element => {
const newKeyframeName = (keyframeName !== undefined) ? `${keyframeName}-alt` : null;
setStyleProperty(element, 'animation-name', newKeyframeName);
});
};
const resetAnimation = () => { const resetAnimation = () => {
if (supportsWebAnimations) { if (supportsWebAnimations) {
setAnimationStep(0); setAnimationStep(0);
} else { } else {
resetCSSAnimations(); updateCSSAnimation();
} }
}; };
@ -973,7 +984,7 @@ export const createAnimation = () => {
*/ */
const play = () => { const play = () => {
if (!initialized) { if (!initialized) {
initializeAnimation(false); initializeAnimation();
} }
if (finished) { if (finished) {