104 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			104 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| /**
 | |
|  * @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 {AnimationMetadata, AnimationPlayer, AnimationTriggerMetadata} from '@angular/animations';
 | |
| import {TriggerAst} from '../dsl/animation_ast';
 | |
| import {buildAnimationAst} from '../dsl/animation_ast_builder';
 | |
| import {AnimationTrigger, buildTrigger} from '../dsl/animation_trigger';
 | |
| import {AnimationStyleNormalizer} from '../dsl/style_normalization/animation_style_normalizer';
 | |
| 
 | |
| import {AnimationDriver} from './animation_driver';
 | |
| import {parseTimelineCommand} from './shared';
 | |
| import {TimelineAnimationEngine} from './timeline_animation_engine';
 | |
| import {TransitionAnimationEngine} from './transition_animation_engine';
 | |
| 
 | |
| export class AnimationEngine {
 | |
|   private _transitionEngine: TransitionAnimationEngine;
 | |
|   private _timelineEngine: TimelineAnimationEngine;
 | |
| 
 | |
|   private _triggerCache: {[key: string]: AnimationTrigger} = {};
 | |
| 
 | |
|   // this method is designed to be overridden by the code that uses this engine
 | |
|   public onRemovalComplete = (element: any, context: any) => {};
 | |
| 
 | |
|   constructor(driver: AnimationDriver, normalizer: AnimationStyleNormalizer) {
 | |
|     this._transitionEngine = new TransitionAnimationEngine(driver, normalizer);
 | |
|     this._timelineEngine = new TimelineAnimationEngine(driver, normalizer);
 | |
| 
 | |
|     this._transitionEngine.onRemovalComplete = (element: any, context: any) =>
 | |
|         this.onRemovalComplete(element, context);
 | |
|   }
 | |
| 
 | |
|   registerTrigger(
 | |
|       componentId: string, namespaceId: string, hostElement: any, name: string,
 | |
|       metadata: AnimationTriggerMetadata): void {
 | |
|     const cacheKey = componentId + '-' + name;
 | |
|     let trigger = this._triggerCache[cacheKey];
 | |
|     if (!trigger) {
 | |
|       const errors: any[] = [];
 | |
|       const ast = buildAnimationAst(metadata as AnimationMetadata, errors) as TriggerAst;
 | |
|       if (errors.length) {
 | |
|         throw new Error(
 | |
|             `The animation trigger "${name}" has failed to build due to the following errors:\n - ${errors.join("\n - ")}`);
 | |
|       }
 | |
|       trigger = buildTrigger(name, ast);
 | |
|       this._triggerCache[cacheKey] = trigger;
 | |
|     }
 | |
|     this._transitionEngine.registerTrigger(namespaceId, name, trigger);
 | |
|   }
 | |
| 
 | |
|   register(namespaceId: string, hostElement: any) {
 | |
|     this._transitionEngine.register(namespaceId, hostElement);
 | |
|   }
 | |
| 
 | |
|   destroy(namespaceId: string, context: any) {
 | |
|     this._transitionEngine.destroy(namespaceId, context);
 | |
|   }
 | |
| 
 | |
|   onInsert(namespaceId: string, element: any, parent: any, insertBefore: boolean): void {
 | |
|     this._transitionEngine.insertNode(namespaceId, element, parent, insertBefore);
 | |
|   }
 | |
| 
 | |
|   onRemove(namespaceId: string, element: any, context: any): void {
 | |
|     this._transitionEngine.removeNode(namespaceId, element, context);
 | |
|   }
 | |
| 
 | |
|   disableAnimations(element: any, disable: boolean) {
 | |
|     this._transitionEngine.markElementAsDisabled(element, disable);
 | |
|   }
 | |
| 
 | |
|   process(namespaceId: string, element: any, property: string, value: any) {
 | |
|     if (property.charAt(0) == '@') {
 | |
|       const [id, action] = parseTimelineCommand(property);
 | |
|       const args = value as any[];
 | |
|       this._timelineEngine.command(id, element, action, args);
 | |
|     } else {
 | |
|       this._transitionEngine.trigger(namespaceId, element, property, value);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   listen(
 | |
|       namespaceId: string, element: any, eventName: string, eventPhase: string,
 | |
|       callback: (event: any) => any): () => any {
 | |
|     // @@listen
 | |
|     if (eventName.charAt(0) == '@') {
 | |
|       const [id, action] = parseTimelineCommand(eventName);
 | |
|       return this._timelineEngine.listen(id, element, action, callback);
 | |
|     }
 | |
|     return this._transitionEngine.listen(namespaceId, element, eventName, eventPhase, callback);
 | |
|   }
 | |
| 
 | |
|   flush(microtaskId: number = -1): void { this._transitionEngine.flush(microtaskId); }
 | |
| 
 | |
|   get players(): AnimationPlayer[] {
 | |
|     return (this._transitionEngine.players as AnimationPlayer[])
 | |
|         .concat(this._timelineEngine.players as AnimationPlayer[]);
 | |
|   }
 | |
| 
 | |
|   whenRenderingDone(): Promise<any> { return this._transitionEngine.whenRenderingDone(); }
 | |
| }
 |