Переиспользуемые анимации в Angular

Для создания анимации используется функция animation(). Для её использования — useAnimation()

// создание анимации
const myAnimation = animation('{{ timings }}', []);

// использование анимации
trigger('myTrigger', 
  transition('* => *',
    useAnimation(myAnimation, { params: { timings: 200 } })
  )
);

Пример переиспользуемой анимации

Файл с анимацией

import {
  animate,
  animation,
  keyframes,
  style,
} from '@angular/animations';

export const insertTableRow = animation([       // <<=== первая анимация
  animate(
    '500ms ease-in',
    keyframes([
      style({ backgroundColor: '*', opacity: 0 }),
      style({ backgroundColor: 'lightgreen', opacity: 0.5 }),
      style({ backgroundColor: '*', opacity: 1 }),
    ])
  ),
]);

export const removeTableRow = animation([       // <<=== вторая анимация
  animate('500ms ease-in', style({ opacity: 0, backgroundColor: 'red' })),
]);

Использование

@Component({
  selector: 'my-table',
  templateUrl: 'my-table.component.html',
  styleUrls: ['./my-table.scss'],
  animations: [
    trigger('rowAnimate', [
      transition(':enter', useAnimation(insertTableRow)),   // <<=== использование
      transition(':leave', useAnimation(removeTableRow)),
    ]),
  ],
  changeDetection: ChangeDetectionStrategy.OnPush,
})

Под капотом.

import { AnimationAnimateMetadata, AnimationMetadataType } from '@angular/animations';

/**
 * Анимация вставки строки
 * ```
 * animate('500ms ease-in', keyframes([
 *   style({ backgroundColor: '*', opacity: 0 }),
 *   style({ backgroundColor: 'lightgreen', opacity:0.5 }),
 *   style({ backgroundColor: '*', opacity: 1 })
 * ])),
 * ```
 */
export const insertTableRow = <AnimationAnimateMetadata>{
  type: AnimationMetadataType.Animate,
  timings: '500ms ease-in',
  styles: {
    offset: null,
    type: AnimationMetadataType.Keyframes,
    steps: [
      {
        type: AnimationMetadataType.Style,
        styles: {
          backgroundColor: '*',
          opacity: 0,
        },
        offset: null,
      },
      {
        type: AnimationMetadataType.Style,
        styles: {
          backgroundColor: 'lightgreen',
          opacity: 0.5,
        },
        offset: null,
      },
      {
        type: AnimationMetadataType.Style,
        styles: {
          backgroundColor: '*',
          opacity: 1,
        },
        offset: null,
      },
    ],
  },
};

/**
 * Анимация удаления строки
 * ```
 * animate('500ms ease-in', style({ opacity: 0, backgroundColor: 'red' })),
 * ```
 */
export const removeTableRow = <AnimationAnimateMetadata>{
  type: AnimationMetadataType.Animate,
  timings: '500ms ease-in',
  styles: {
    type: AnimationMetadataType.Style,
    styles: {
      backgroundColor: 'red',
      opacity: 0,
    },
    offset: null,
  },
};

Использование

@Component({
  selector: 'isp-site-table-list',
  templateUrl: 'site-table-list.component.html',
  styleUrls: ['./scss/site-table-list/_isp-site-table-list.scss'],
  animations: [
    trigger('rowAnimate', [
      transition(':enter', [insertTableRow]),
      transition(':leave', [removeTableRow]),
    ]),
  ],
  changeDetection: ChangeDetectionStrategy.OnPush,
})

Похожие записи

RxJS Pipeable Operators

Начиная с версии rxjs 5.5 операторы вместо цепочки вызовов применяются как параметры функции pipe.