2

How to add animation programatically ?

@Component({
    moduleId: module.id,
    selector: 'my-toolbar',
    templateUrl: './my-toolbar.component.html',
    styleUrls: ['./my-toolbar.component.scss'],
    encapsulation: ViewEncapsulation.None,
    animations: [
        trigger('myToolbarState', [
            state('initial', style({top: '*'})),
            state('up', style({top: '-50px')),
            transition('initial => up, up => initial',
                animate(HEADER_SHRINK_TRANSITION))
        ])
    ]
})

How to achieve the same without annotation ? My underlying goal is to create a dynamic trigger function that uses different values based on some @Input.

It is important to note that the animations or the triggers must have at-least one variable. That makes this question different from how do I reuse animations.

bhantol
  • 9,368
  • 7
  • 44
  • 81
  • Possible duplicate of [How do you create reusable Animations in Angular 2](https://stackoverflow.com/questions/39463360/how-do-you-create-reusable-animations-in-angular-2) – Alex Beugnet Sep 11 '17 at 23:20
  • You can also look at this NG2 issue : https://github.com/angular/angular/issues/9947 – Alex Beugnet Sep 11 '17 at 23:21
  • The question https://stackoverflow.com/questions/39463360/how-do-you-create-reusable-animations-in-angular-2 and numerous solutions only reuse without any dynamic parameters. In this case the animations must be driven by `@Input()` or some variable inside the Component class. – bhantol Sep 12 '17 at 04:55

1 Answers1

1

I ended up with following factory class as shown below being used for animations[]:-

This is used as below:

@Component({
  selector: 'my-app-header',
  moduleId: module.id,
  templateUrl: './app-header.component.html',
  styleUrls: ['./app-header.component.scss'],
  animations: [
      MyToolbarAnimator.createTrigger('appHeaderState', '50px', '0')
  ]
})

Defined MyToolbarAnimator with a static method createTrigger which returns AnimationTriggerMetadata as shown below

MyToolbarAnimator

import {trigger, state, style, animate, transition, AnimationTriggerMetadata} from '@angular/animations';

export const HEADER_SHRINK_TRANSITION = '250ms cubic-bezier(0.4,0.0,0.2,1)';

export class MyToolbarAnimator {
    static createTrigger(triggerName: string, initialTop: string, upTop: string): AnimationTriggerMetadata {
        return trigger(triggerName, [
            state('initial', style({top: initialTop})),
            state('up', style({top: upTop})),
            transition('initial => up, up => initial',
                animate(HEADER_SHRINK_TRANSITION))
        ]);
    }
}

UPDATE:

Or if your animation parameters are very dynamic and changes based on the component behavior use https://angular.io/api/animations/AnimationBuilder#usage-notes This

// import the service from BrowserAnimationsModule
import {AnimationBuilder} from '@angular/animations';
// require the service as a dependency
class MyCmp {
  width = 100;
  constructor(private _builder: AnimationBuilder) {}
  changeWidth(aWidth:number) {
      this.width = aWidth;
  }
  makeAnimation(element: any) {
    // first define a reusable animation
    const myAnimation = this._builder.build([
      style({ width: 0 }),
      animate(1000, style({ width: `${this.width}px` }))
    ]);

    // use the returned factory object to create a player
    const player = myAnimation.create(element);

    player.play();
  }
}
bhantol
  • 9,368
  • 7
  • 44
  • 81
  • 1
    In the question you said you want to use values from inputs, but it is unclear from this where exactly is the use of input value here? – Shachar Har-Shuv Jul 16 '20 at 14:10
  • @ShacharHar-Shuv I updated additional option with a animation builder however you can reuse the same `MyToolbarAnimator.createTrigger` in different components passing different set of inputs which is what you want most of the time. – bhantol Jul 21 '20 at 15:22