fix(animations): repair flicker issues with WA polyfill (#16937)
Fixes #16919 Fixes #16918
This commit is contained in:
parent
08dfe91b95
commit
e7d9fd8056
@ -5,6 +5,8 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
import {dashCaseToCamelCase} from '../../util';
|
||||||
|
|
||||||
import {AnimationStyleNormalizer} from './animation_style_normalizer';
|
import {AnimationStyleNormalizer} from './animation_style_normalizer';
|
||||||
|
|
||||||
export class WebAnimationsStyleNormalizer extends AnimationStyleNormalizer {
|
export class WebAnimationsStyleNormalizer extends AnimationStyleNormalizer {
|
||||||
@ -41,8 +43,3 @@ function makeBooleanMap(keys: string[]): {[key: string]: boolean} {
|
|||||||
keys.forEach(key => map[key] = true);
|
keys.forEach(key => map[key] = true);
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DASH_CASE_REGEXP = /-+([a-z0-9])/g;
|
|
||||||
export function dashCaseToCamelCase(input: string): string {
|
|
||||||
return input.replace(DASH_CASE_REGEXP, (...m: any[]) => m[1].toUpperCase());
|
|
||||||
}
|
|
||||||
|
@ -997,9 +997,8 @@ export class TransitionAnimationEngine {
|
|||||||
});
|
});
|
||||||
|
|
||||||
allConsumedElements.forEach(element => addClass(element, NG_ANIMATING_CLASSNAME));
|
allConsumedElements.forEach(element => addClass(element, NG_ANIMATING_CLASSNAME));
|
||||||
|
|
||||||
const player = optimizeGroupPlayer(allNewPlayers);
|
const player = optimizeGroupPlayer(allNewPlayers);
|
||||||
player.onDone(() => {
|
player.onDestroy(() => {
|
||||||
allConsumedElements.forEach(element => removeClass(element, NG_ANIMATING_CLASSNAME));
|
allConsumedElements.forEach(element => removeClass(element, NG_ANIMATING_CLASSNAME));
|
||||||
setStyles(rootElement, instruction.toStyles);
|
setStyles(rootElement, instruction.toStyles);
|
||||||
});
|
});
|
||||||
|
@ -53,6 +53,11 @@ export class WebAnimationsPlayer implements AnimationPlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init(): void {
|
init(): void {
|
||||||
|
this._buildPlayer();
|
||||||
|
this._preparePlayerBeforeStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _buildPlayer(): void {
|
||||||
if (this._initialized) return;
|
if (this._initialized) return;
|
||||||
this._initialized = true;
|
this._initialized = true;
|
||||||
|
|
||||||
@ -82,14 +87,16 @@ export class WebAnimationsPlayer implements AnimationPlayer {
|
|||||||
|
|
||||||
this._player = this._triggerWebAnimation(this.element, keyframes, this.options);
|
this._player = this._triggerWebAnimation(this.element, keyframes, this.options);
|
||||||
this._finalKeyframe = keyframes.length ? keyframes[keyframes.length - 1] : {};
|
this._finalKeyframe = keyframes.length ? keyframes[keyframes.length - 1] : {};
|
||||||
|
this._player.addEventListener('finish', () => this._onFinish());
|
||||||
|
}
|
||||||
|
|
||||||
|
private _preparePlayerBeforeStart() {
|
||||||
// this is required so that the player doesn't start to animate right away
|
// this is required so that the player doesn't start to animate right away
|
||||||
if (this._delay) {
|
if (this._delay) {
|
||||||
this._resetDomPlayerState();
|
this._resetDomPlayerState();
|
||||||
} else {
|
} else {
|
||||||
this._player.pause();
|
this._player.pause();
|
||||||
}
|
}
|
||||||
this._player.addEventListener('finish', () => this._onFinish());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
@ -108,7 +115,7 @@ export class WebAnimationsPlayer implements AnimationPlayer {
|
|||||||
onDestroy(fn: () => void): void { this._onDestroyFns.push(fn); }
|
onDestroy(fn: () => void): void { this._onDestroyFns.push(fn); }
|
||||||
|
|
||||||
play(): void {
|
play(): void {
|
||||||
this.init();
|
this._buildPlayer();
|
||||||
if (!this.hasStarted()) {
|
if (!this.hasStarted()) {
|
||||||
this._onStartFns.forEach(fn => fn());
|
this._onStartFns.forEach(fn => fn());
|
||||||
this._onStartFns = [];
|
this._onStartFns = [];
|
||||||
|
@ -123,16 +123,18 @@ export function copyStyles(
|
|||||||
|
|
||||||
export function setStyles(element: any, styles: ɵStyleData) {
|
export function setStyles(element: any, styles: ɵStyleData) {
|
||||||
if (element['style']) {
|
if (element['style']) {
|
||||||
Object.keys(styles).forEach(prop => element.style[prop] = styles[prop]);
|
Object.keys(styles).forEach(prop => {
|
||||||
|
const camelProp = dashCaseToCamelCase(prop);
|
||||||
|
element.style[camelProp] = styles[prop];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function eraseStyles(element: any, styles: ɵStyleData) {
|
export function eraseStyles(element: any, styles: ɵStyleData) {
|
||||||
if (element['style']) {
|
if (element['style']) {
|
||||||
Object.keys(styles).forEach(prop => {
|
Object.keys(styles).forEach(prop => {
|
||||||
// IE requires '' instead of null
|
const camelProp = dashCaseToCamelCase(prop);
|
||||||
// see https://github.com/angular/angular/issues/7916
|
element.style[camelProp] = '';
|
||||||
element.style[prop] = '';
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -206,3 +208,8 @@ export function mergeAnimationOptions(
|
|||||||
}
|
}
|
||||||
return destination;
|
return destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DASH_CASE_REGEXP = /-+([a-z0-9])/g;
|
||||||
|
export function dashCaseToCamelCase(input: string): string {
|
||||||
|
return input.replace(DASH_CASE_REGEXP, (...m: any[]) => m[1].toUpperCase());
|
||||||
|
}
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
import {DOMAnimation} from '../../../src/render/web_animations/dom_animation';
|
||||||
|
import {WebAnimationsPlayer} from '../../../src/render/web_animations/web_animations_player';
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
let element: any;
|
||||||
|
let innerPlayer: MockDomAnimation|null = null;
|
||||||
|
beforeEach(() => {
|
||||||
|
element = {};
|
||||||
|
element['animate'] = () => { return innerPlayer = new MockDomAnimation(); };
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('WebAnimationsPlayer tests', () => {
|
||||||
|
it('should automatically pause the player when created and initialized', () => {
|
||||||
|
const keyframes = [
|
||||||
|
{opacity: 0, offset: 0},
|
||||||
|
{opacity: 1, offset: 1},
|
||||||
|
];
|
||||||
|
|
||||||
|
const player = new WebAnimationsPlayer(element, keyframes, {duration: 1000});
|
||||||
|
|
||||||
|
player.init();
|
||||||
|
const p = innerPlayer !;
|
||||||
|
expect(p.log).toEqual(['pause']);
|
||||||
|
|
||||||
|
player.play();
|
||||||
|
expect(p.log).toEqual(['pause', 'play']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not pause the player if created and started before initialized', () => {
|
||||||
|
const keyframes = [
|
||||||
|
{opacity: 0, offset: 0},
|
||||||
|
{opacity: 1, offset: 1},
|
||||||
|
];
|
||||||
|
|
||||||
|
const player = new WebAnimationsPlayer(element, keyframes, {duration: 1000});
|
||||||
|
|
||||||
|
player.play();
|
||||||
|
const p = innerPlayer !;
|
||||||
|
expect(p.log).toEqual(['play']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockDomAnimation implements DOMAnimation {
|
||||||
|
log: string[] = [];
|
||||||
|
cancel(): void { this.log.push('cancel'); }
|
||||||
|
play(): void { this.log.push('play'); }
|
||||||
|
pause(): void { this.log.push('pause'); }
|
||||||
|
finish(): void { this.log.push('finish'); }
|
||||||
|
onfinish: Function = () => {};
|
||||||
|
position: number = 0;
|
||||||
|
currentTime: number = 0;
|
||||||
|
addEventListener(eventName: string, handler: (event: any) => any): any {}
|
||||||
|
dispatchEvent(eventName: string): any {}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user