angular-cn/packages/animations/browser/src/dsl/animation_transition_factory.ts

75 lines
2.9 KiB
TypeScript
Raw Normal View History

/**
* @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 {AnimationOptions, ɵStyleData} from '@angular/animations';
import {getOrSetAsInMap} from '../render/shared';
import {iteratorToArray, mergeAnimationOptions} from '../util';
import {TransitionAst} from './animation_ast';
import {buildAnimationTimelines} from './animation_timeline_builder';
import {TransitionMatcherFn} from './animation_transition_expr';
import {AnimationTransitionInstruction, createTransitionInstruction} from './animation_transition_instruction';
import {ElementInstructionMap} from './element_instruction_map';
export class AnimationTransitionFactory {
constructor(
private _triggerName: string, public ast: TransitionAst,
private _stateStyles: {[stateName: string]: ɵStyleData}) {}
match(currentState: any, nextState: any): boolean {
return oneOrMoreTransitionsMatch(this.ast.matchers, currentState, nextState);
}
build(
element: any, currentState: any, nextState: any, options?: AnimationOptions,
subInstructions?: ElementInstructionMap): AnimationTransitionInstruction|undefined {
const animationOptions = mergeAnimationOptions(this.ast.options || {}, options || {});
const backupStateStyles = this._stateStyles['*'] || {};
const currentStateStyles = this._stateStyles[currentState] || backupStateStyles;
const nextStateStyles = this._stateStyles[nextState] || backupStateStyles;
const errors: any[] = [];
const timelines = buildAnimationTimelines(
element, this.ast.animation, currentStateStyles, nextStateStyles, animationOptions,
subInstructions, errors);
if (errors.length) {
const errorMessage = `animation building failed:\n${errors.join("\n")}`;
throw new Error(errorMessage);
}
const preStyleMap = new Map<any, {[prop: string]: boolean}>();
const postStyleMap = new Map<any, {[prop: string]: boolean}>();
const queriedElements = new Set<any>();
timelines.forEach(tl => {
const elm = tl.element;
const preProps = getOrSetAsInMap(preStyleMap, elm, {});
tl.preStyleProps.forEach(prop => preProps[prop] = true);
const postProps = getOrSetAsInMap(postStyleMap, elm, {});
tl.postStyleProps.forEach(prop => postProps[prop] = true);
if (elm !== element) {
queriedElements.add(elm);
}
});
const queriedElementsList = iteratorToArray(queriedElements.values());
return createTransitionInstruction(
element, this._triggerName, currentState, nextState, nextState === 'void',
currentStateStyles, nextStateStyles, timelines, queriedElementsList, preStyleMap,
postStyleMap);
}
}
function oneOrMoreTransitionsMatch(
matchFns: TransitionMatcherFn[], currentState: any, nextState: any): boolean {
return matchFns.some(fn => fn(currentState, nextState));
}