DEV Community

Cover image for GSAP Animations in Angular - Animation Directives
Nicola
Nicola

Posted on

GSAP Animations in Angular - Animation Directives

Create a directive for animation

As the second part of this tutorial we will create an attribute-directive, which will define a specific animation and its attributes.

We will start with a simple FadeIn animation.

But before starting with the real directive, we are going to create a generic class which will be extended by arbitrary directives, called CoreAnimationDirective.

The goal of this directive is to define the standard methods and attributes for our future animation directives, to prevent a lot of repeats and hard-to-mantain directives.

The CoreAnimationDirective class

Let's create! Before doing anything, let's create a specific folder for gsap directive.

From 'src/app' run in terminal mkdir directives\gsap.

Note: use \ or / directory separator according to your system.

Your project should look like this:

Project structure

Let's create the class, move to the gsap directory cd directives\gsap & echo > core-animation.directive.ts.

Open the file and write the following:

import {ElementRef, EventEmitter, Input, Output} from '@angular/core';
import {TimelineMax} from 'gsap';

export class CoreAnimationDirective {
  @Input() duration = 1;
  @Input() delay = 0;

  @Output() complete: EventEmitter<null> = new EventEmitter();
  @Output() reverseComplete: EventEmitter<null> = new EventEmitter();
  protected timeline: TimelineMax;

  constructor(protected element: ElementRef) {}
}

A little bit of explanation:

  • @Input() duration - the duration of the animation
  • @Input() delay - the delay of the animation
  • @Output() complete - event emitter for the animation complete callback
  • @Output() reverseComplete - event emitter for the animation reverseComplete callback
  • protected timeline: TimelineMax - the timeline for animation

Check the docs about TimelineMax and eventCallbacks here.

The constructor have only 1 param, the element (ElementRef), it's the ref to the native element which uses the directive.

We need to instantiate our timeline before animating it inside the constructor:

constructor(protected element: ElementRef) {
  this.timeline = new TimelineMax({
    onComplete: _ => this.complete.emit(),
    onReverseComplete: _ => this.reverseComplete.emit(),
    paused:true,
    reversed:true
  });
}

This piece of code will create a new timeline, paused and not reversed, with a onComplete and onReverseComplete callback.

Let's create the animateIn method:

protected animateIn() {
  if(this.timeline.isActive()) {
    this.timeline.kill();
  }
  this.timeline.play();
}

This method will kill the animation if in progress (you can return if is active so it will not stop), and play the current animation.

The FadeInDirective class

Let's proceed with the next class, this class will perform the real animation.

It will extend the CoreAnimationClass, as we don't need to repeat some portions of code.

Inside the gsap folder we've created previously, run echo > fade-in-animation.directive.ts and write the following code inside:

import { Directive, OnInit, OnDestroy, ViewContainerRef, ElementRef, Input, EventEmitter } from '@angular/core';
import { TimelineMax } from 'gsap';
import { CoreAnimationDirective } from './core-animation.directive';

@Directive({
  selector: '[fadeInAnimation]'
})
export class FadeInAnimationDirective extends CoreAnimationDirective implements OnInit {
  constructor(protected element: ElementRef) {
    super(element);
  }

  ngOnInit() {
    // perform animation
    this.animateIn();
  }

  protected animateIn() {
    this.timeline.from(this.element.nativeElement, this.duration, {opacity:'0', ease:"Expo.easeInOut"}, this.delay);
    super.animateIn();
  }
}

This component extends the CoreAnimationDirective, so we don't need to define the @Input, @Output and other properties twice.

We need to create the opacity animation using this.timeline.from as follow:

this.timeline.from(this.element.nativeElement, this.duration, {opacity:'0', ease:"Expo.easeInOut"}, this.delay);

This will perform an animation on element opacity, from 0 to 1 (or to element opacity current value).

Top comments (0)