fix(animations): retain styling when transition destinations are changed (#12208)

Closes #9661
Closes #12208
This commit is contained in:
Matias Niemelä
2016-11-14 16:59:06 -08:00
committed by Victor Berchet
parent 46023e4792
commit 9de76ebfa5
24 changed files with 403 additions and 79 deletions

View File

@ -89,7 +89,7 @@ export class MessageBasedRenderer {
'animate',
[
RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE, PRIMITIVE, PRIMITIVE,
PRIMITIVE, PRIMITIVE
PRIMITIVE, PRIMITIVE, PRIMITIVE
],
this._animate.bind(this));
@ -248,8 +248,14 @@ export class MessageBasedRenderer {
private _animate(
renderer: Renderer, element: any, startingStyles: any, keyframes: any[], duration: number,
delay: number, easing: string, playerId: any) {
const player = renderer.animate(element, startingStyles, keyframes, duration, delay, easing);
delay: number, easing: string, previousPlayers: number[], playerId: any) {
let normalizedPreviousPlayers: AnimationPlayer[];
if (previousPlayers && previousPlayers.length) {
normalizedPreviousPlayers =
previousPlayers.map(playerId => this._renderStore.deserialize(playerId));
}
const player = renderer.animate(
element, startingStyles, keyframes, duration, delay, easing, normalizedPreviousPlayers);
this._renderStore.store(player, playerId);
}

View File

@ -16,6 +16,7 @@ import {MessageBus} from '../shared/message_bus';
import {EVENT_CHANNEL, RENDERER_CHANNEL} from '../shared/messaging_api';
import {RenderStore} from '../shared/render_store';
import {ANIMATION_WORKER_PLAYER_PREFIX, RenderStoreObject, Serializer} from '../shared/serializer';
import {deserializeGenericEvent} from './event_deserializer';
@Injectable()
@ -239,13 +240,16 @@ export class WebWorkerRenderer implements Renderer, RenderStoreObject {
animate(
renderElement: any, startingStyles: AnimationStyles, keyframes: AnimationKeyframe[],
duration: number, delay: number, easing: string): AnimationPlayer {
duration: number, delay: number, easing: string,
previousPlayers: AnimationPlayer[] = []): AnimationPlayer {
const playerId = this._rootRenderer.allocateId();
const previousPlayerIds: number[] =
previousPlayers.map(player => this._rootRenderer.renderStore.serialize(player));
this._runOnService('animate', [
new FnArg(renderElement, RenderStoreObject), new FnArg(startingStyles, null),
new FnArg(keyframes, null), new FnArg(duration, null), new FnArg(delay, null),
new FnArg(easing, null), new FnArg(playerId, null)
new FnArg(easing, null), new FnArg(previousPlayerIds, null), new FnArg(playerId, null)
]);
const player = new _AnimationWorkerRendererPlayer(this._rootRenderer, renderElement);
@ -325,7 +329,7 @@ export class WebWorkerRenderNode {
animationPlayerEvents = new AnimationPlayerEmitter();
}
class _AnimationWorkerRendererPlayer implements AnimationPlayer, RenderStoreObject {
class _AnimationWorkerRendererPlayer implements RenderStoreObject {
public parentPlayer: AnimationPlayer = null;
private _destroyed: boolean = false;

View File

@ -289,6 +289,30 @@ export function main() {
expect(player.log.indexOf('destroy') >= 0).toBe(true);
}));
it('should properly transition to the next animation if the current one is cancelled',
fakeAsync(() => {
const fixture = TestBed.createComponent(AnimationCmp);
const cmp = fixture.componentInstance;
cmp.state = 'on';
fixture.detectChanges();
flushMicrotasks();
let player = <MockAnimationPlayer>uiDriver.log.shift()['player'];
player.finish();
player = <MockAnimationPlayer>uiDriver.log.shift()['player'];
player.setPosition(0.5);
uiDriver.log = [];
cmp.state = 'off';
fixture.detectChanges();
flushMicrotasks();
const step = uiDriver.log.shift();
expect(step['previousStyles']).toEqual({opacity: AUTO_STYLE, fontSize: AUTO_STYLE});
}));
});
}