18

The @Component annotation provides us with an animations property. This can be used to define a list of triggers each with a lot of state and transition properties.

When you add multiple animations to a component, this list can become pretty long. Also some animations would be really nice to use in other components as well. Having to put them directly in each component seems tedious and is repetitive - plus it violates the DRY principle.

You can define the template and styles properties on your component as well, but here you have the option of providing a templateUrl and styleUrls instead. I can't seem to find an animationUrls property - am i missing something - is there a way to do this?

Per Hornshøj-Schierbeck
  • 15,097
  • 21
  • 80
  • 101

4 Answers4

35

Sure you can. You can just declare the animation in a different file, then import it where you need it

animations.ts

export const animation = trigger(...)

component.ts

import { animation } from './animations'

@Component({
  animations: [ animation ]
})

Or if you want to make it configurable, you can export a function. For example, take a look at the Fuel-UI Collapse. This is a reusable (and configurable) animation

collapse.ts

export function Collapse(duration: number = 300) {
    return trigger('collapse', [
           ...
        ])
}

Then in your components, just use

import { Collapse } from './collapse'

@Component({
  animations: [ Collapse(300) ],
  template: `
    <div @collapse="collapsed ? 'true' : 'false'">
    </div>
  `
})
class MyComponent {}
Chris Stillwell
  • 10,266
  • 10
  • 67
  • 77
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
4

Sure that's possible. You can make for instance an animations.ts and let it export all kind of animation constants:

export const PRETTY_ANIMATION = trigger('heroState', [
  state('inactive', style({
    backgroundColor: '#eee',
    transform: 'scale(1)'
  })),
  state('active',   style({
    backgroundColor: '#cfd8dc',
    transform: 'scale(1.1)'
  })),
  transition('inactive => active', animate('100ms ease-in')),
  transition('active => inactive', animate('100ms ease-out'))
])

and in your component you can import this animation using the import statement:

import {PRETTY_ANIMATION} from 'animations';

and apply it to your component:

@Component({
    selector : `...`
    animations : [PRETTY_ANIMATION]
})
Chris Stillwell
  • 10,266
  • 10
  • 67
  • 77
Poul Kruijt
  • 69,713
  • 12
  • 145
  • 149
1

You certainly and the gentlemen has done so in some of his github repo examples. Take the following:

route_animations.ts

import {
    trigger,
    animate,
    style,
    transition
} from '@angular/core';

var startingStyles = (styles) => {
    styles['position'] = 'fixed';
    styles['top'] = 0;
    styles['left'] = 0;
    styles['right'] = 0;
    styles['height'] = '100%';
    return styles;
}

export default function(name) {
    return trigger(name, [
        transition('void => *', [
            style(startingStyles({
                transform: 'translateX(100%)'
            })),
            animate('0.5s ease-out', style({ transform: 'translateX(0%)'}))
        ]),
        transition('* => void', [
            style(startingStyles({
                transform: 'translateX(0%)'
            })),
            animate('0.5s ease-in', style({ transform: 'translateX(-100%)'}))
        ])
    ]);
}

Which is then imported into a component like the following:

import {default as routerAnimations} from '../route_animations';

And then called like this under the animation Param when initialising the component:

animations: [routerAnimations('route')],

Take a look at this yourself to get a better idea but I hope this helps. https://github.com/matsko/ng2eu-2016-code/blob/master

Kudos to matsko.

Chris Stillwell
  • 10,266
  • 10
  • 67
  • 77
Nige
  • 1,206
  • 2
  • 10
  • 21
1

Here's another example fade in animation in Angular 4 I use for animating routes

// import the required animation functions from the angular animations module
import { trigger, state, animate, transition, style } from '@angular/animations';
 
export const fadeInAnimation =
    // trigger name for attaching this animation to an element using the [@triggerName] syntax
    trigger('fadeInAnimation', [
 
        // route 'enter' transition
        transition(':enter', [
 
            // css styles at start of transition
            style({ opacity: 0 }),
 
            // animation and styles at end of transition
            animate('.3s', style({ opacity: 1 }))
        ]),
    ]);

And a component with the transition attached

import { Component } from '@angular/core';
 
// import fade in animation
import { fadeInAnimation } from '../_animations/index';
 
@Component({
    moduleId: module.id.toString(),
    templateUrl: 'home.component.html',
 
    // make fade in animation available to this component
    animations: [fadeInAnimation],
 
    // attach the fade in animation to the host (root) element of this component
    host: { '[@fadeInAnimation]': '' }
})
 
export class HomeComponent {
}

More details and a live demo at this post

Chris Stillwell
  • 10,266
  • 10
  • 67
  • 77
Jason Watmore
  • 4,521
  • 2
  • 32
  • 36
  • thanks for specifying how to do this when not coding in the (unsustainable) template format. :) – tatsu Feb 12 '18 at 13:55