refactor(animations): add an onStart handler for AnimationPlayer (#10360)

This commit is contained in:
Matias Niemelä 2016-08-22 16:39:52 -07:00 committed by Kara
parent 23a27776e2
commit 3c561475c8
10 changed files with 114 additions and 28 deletions

View File

@ -12,7 +12,8 @@ import {Math} from '../facade/math';
import {AnimationPlayer} from './animation_player';
export class AnimationGroupPlayer implements AnimationPlayer {
private _subscriptions: Function[] = [];
private _onDoneFns: Function[] = [];
private _onStartFns: Function[] = [];
private _finished = false;
private _started = false;
@ -41,14 +42,16 @@ export class AnimationGroupPlayer implements AnimationPlayer {
if (!isPresent(this.parentPlayer)) {
this.destroy();
}
this._subscriptions.forEach(subscription => subscription());
this._subscriptions = [];
this._onDoneFns.forEach(fn => fn());
this._onDoneFns = [];
}
}
init(): void { this._players.forEach(player => player.init()); }
onDone(fn: Function): void { this._subscriptions.push(fn); }
onStart(fn: () => void): void { this._onStartFns.push(fn); }
onDone(fn: () => void): void { this._onDoneFns.push(fn); }
hasStarted() { return this._started; }
@ -56,7 +59,11 @@ export class AnimationGroupPlayer implements AnimationPlayer {
if (!isPresent(this.parentPlayer)) {
this.init();
}
this._started = true;
if (!this.hasStarted()) {
this._onStartFns.forEach(fn => fn());
this._onStartFns = [];
this._started = true;
}
this._players.forEach(player => player.play());
}

View File

@ -14,7 +14,8 @@ import {scheduleMicroTask} from '../facade/lang';
* @experimental Animation support is experimental.
*/
export abstract class AnimationPlayer {
abstract onDone(fn: Function): void;
abstract onDone(fn: () => void): void;
abstract onStart(fn: () => void): void;
abstract init(): void;
abstract hasStarted(): boolean;
abstract play(): void;
@ -32,19 +33,27 @@ export abstract class AnimationPlayer {
}
export class NoOpAnimationPlayer implements AnimationPlayer {
private _subscriptions: any[] /** TODO #9100 */ = [];
private _onDoneFns: Function[] = [];
private _onStartFns: Function[] = [];
private _started = false;
public parentPlayer: AnimationPlayer = null;
constructor() { scheduleMicroTask(() => this._onFinish()); }
/** @internal */
_onFinish() {
this._subscriptions.forEach(entry => { entry(); });
this._subscriptions = [];
this._onDoneFns.forEach(fn => fn());
this._onDoneFns = [];
}
onDone(fn: Function): void { this._subscriptions.push(fn); }
onStart(fn: () => void): void { this._onStartFns.push(fn); }
onDone(fn: () => void): void { this._onDoneFns.push(fn); }
hasStarted(): boolean { return this._started; }
init(): void {}
play(): void { this._started = true; }
play(): void {
if (!this.hasStarted()) {
this._onStartFns.forEach(fn => fn());
this._onStartFns = [];
}
this._started = true;
}
pause(): void {}
restart(): void {}
finish(): void { this._onFinish(); }

View File

@ -13,7 +13,8 @@ import {AnimationPlayer, NoOpAnimationPlayer} from './animation_player';
export class AnimationSequencePlayer implements AnimationPlayer {
private _currentIndex: number = 0;
private _activePlayer: AnimationPlayer;
private _subscriptions: Function[] = [];
private _onDoneFns: Function[] = [];
private _onStartFns: Function[] = [];
private _finished = false;
private _started: boolean = false;
@ -50,14 +51,16 @@ export class AnimationSequencePlayer implements AnimationPlayer {
if (!isPresent(this.parentPlayer)) {
this.destroy();
}
this._subscriptions.forEach(subscription => subscription());
this._subscriptions = [];
this._onDoneFns.forEach(fn => fn());
this._onDoneFns = [];
}
}
init(): void { this._players.forEach(player => player.init()); }
onDone(fn: Function): void { this._subscriptions.push(fn); }
onStart(fn: () => void): void { this._onStartFns.push(fn); }
onDone(fn: () => void): void { this._onDoneFns.push(fn); }
hasStarted() { return this._started; }
@ -65,7 +68,11 @@ export class AnimationSequencePlayer implements AnimationPlayer {
if (!isPresent(this.parentPlayer)) {
this.init();
}
this._started = true;
if (!this.hasStarted()) {
this._onStartFns.forEach(fn => fn());
this._onStartFns = [];
this._started = true;
}
this._activePlayer.play();
}

View File

@ -173,6 +173,18 @@ export function main() {
group.destroy();
});
it('should run the onStart method when started but only once', () => {
var player = new AnimationGroupPlayer([]);
var calls = 0;
player.onStart(() => calls++);
expect(calls).toEqual(0);
player.play();
expect(calls).toEqual(1);
player.pause();
player.play();
expect(calls).toEqual(1);
});
it('should call onDone after the next microtask if no players are provided', fakeAsync(() => {
var group = new AnimationGroupPlayer([]);
var completed = false;

View File

@ -29,5 +29,17 @@ export function main() {
player.restart();
player.destroy();
}));
it('should run the onStart method when started but only once', fakeAsync(() => {
var player = new NoOpAnimationPlayer();
var calls = 0;
player.onStart(() => calls++);
expect(calls).toEqual(0);
player.play();
expect(calls).toEqual(1);
player.pause();
player.play();
expect(calls).toEqual(1);
}));
});
}

View File

@ -196,6 +196,18 @@ export function main() {
sequence.destroy();
});
it('should run the onStart method when started but only once', () => {
var player = new AnimationSequencePlayer([]);
var calls = 0;
player.onStart(() => calls++);
expect(calls).toEqual(0);
player.play();
expect(calls).toEqual(1);
player.pause();
player.play();
expect(calls).toEqual(1);
});
it('should call onDone after the next microtask if no players are provided', fakeAsync(() => {
var sequence = new AnimationSequencePlayer([]);
var completed = false;

View File

@ -10,7 +10,8 @@ import {AnimationPlayer} from '../src/animation/animation_player';
import {isPresent} from '../src/facade/lang';
export class MockAnimationPlayer implements AnimationPlayer {
private _subscriptions: any[] /** TODO #9100 */ = [];
private _onDoneFns: Function[] = [];
private _onStartFns: Function[] = [];
private _finished = false;
private _destroyed = false;
private _started: boolean = false;
@ -19,13 +20,13 @@ export class MockAnimationPlayer implements AnimationPlayer {
public log: any[] /** TODO #9100 */ = [];
private _onfinish(): void {
private _onFinish(): void {
if (!this._finished) {
this._finished = true;
this.log.push('finish');
this._subscriptions.forEach((entry) => { entry(); });
this._subscriptions = [];
this._onDoneFns.forEach(fn => fn());
this._onDoneFns = [];
if (!isPresent(this.parentPlayer)) {
this.destroy();
}
@ -34,12 +35,18 @@ export class MockAnimationPlayer implements AnimationPlayer {
init(): void { this.log.push('init'); }
onDone(fn: Function): void { this._subscriptions.push(fn); }
onDone(fn: () => void): void { this._onDoneFns.push(fn); }
onStart(fn: () => void): void { this._onStartFns.push(fn); }
hasStarted() { return this._started; }
play(): void {
this._started = true;
if (!this.hasStarted()) {
this._onStartFns.forEach(fn => fn());
this._onStartFns = [];
this._started = true;
}
this.log.push('play');
}
@ -47,7 +54,7 @@ export class MockAnimationPlayer implements AnimationPlayer {
restart(): void { this.log.push('restart'); }
finish(): void { this._onfinish(); }
finish(): void { this._onFinish(); }
reset(): void { this.log.push('reset'); }

View File

@ -16,7 +16,8 @@ import {getDOM} from './dom_adapter';
import {DomAnimatePlayer} from './dom_animate_player';
export class WebAnimationsPlayer implements AnimationPlayer {
private _subscriptions: Function[] = [];
private _onDoneFns: Function[] = [];
private _onStartFns: Function[] = [];
private _finished = false;
private _initialized = false;
private _player: DomAnimatePlayer;
@ -37,8 +38,8 @@ export class WebAnimationsPlayer implements AnimationPlayer {
if (!isPresent(this.parentPlayer)) {
this.destroy();
}
this._subscriptions.forEach(fn => fn());
this._subscriptions = [];
this._onDoneFns.forEach(fn => fn());
this._onDoneFns = [];
}
}
@ -66,10 +67,17 @@ export class WebAnimationsPlayer implements AnimationPlayer {
return <DomAnimatePlayer>element.animate(keyframes, options);
}
onDone(fn: Function): void { this._subscriptions.push(fn); }
onStart(fn: () => void): void { this._onStartFns.push(fn); }
onDone(fn: () => void): void { this._onDoneFns.push(fn); }
play(): void {
this.init();
if (!this.hasStarted()) {
this._onStartFns.forEach(fn => fn());
this._onStartFns = [];
this._started = true;
}
this._player.play();
}

View File

@ -128,5 +128,16 @@ export function main() {
expect(captures2['finish'].length).toEqual(1);
expect(captures2['cancel'].length).toEqual(0);
});
it('should run the onStart method when started but only once', () => {
var calls = 0;
player.onStart(() => calls++);
expect(calls).toEqual(0);
player.play();
expect(calls).toEqual(1);
player.pause();
player.play();
expect(calls).toEqual(1);
});
});
}

View File

@ -69,7 +69,8 @@ export declare abstract class AnimationPlayer {
abstract getPosition(): number;
abstract hasStarted(): boolean;
abstract init(): void;
abstract onDone(fn: Function): void;
abstract onDone(fn: () => void): void;
abstract onStart(fn: () => void): void;
abstract pause(): void;
abstract play(): void;
abstract reset(): void;