Search code examples
angularangular-animations

How to create shake animation in Angular 6?


How can we create a shake animation using Angular 6 animations? The animation should look like 'shake' animation in Animate.css


Solution

  • This is a little bit tricky, if you want to apply the animation to several elements within one component in Angular 6:

    app.component.html:

    <p [@shakeit]="this.states['state1']" (click)="shakeMe('state1')" (@shakeit.done)="shakeEnd('state1', $event)">Click me</p>
    
    <p [@shakeit]="this.states['state2']" (click)="shakeMe('state2')" (@shakeit.done)="shakeEnd('state2', $event)">Click me</p>
    

    app.component.ts:

    import { Component } from '@angular/core';
    import { trigger,state,style,transition,animate,keyframes } from    '@angular/animations';
    
    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html',
      styleUrls: [ './app.component.css' ],
      animations: [
        trigger('shakeit', [
            state('shakestart', style({
                transform: 'scale(1)',
            })),
            state('shakeend', style({
                transform: 'scale(1)',
            })),
            transition('shakestart => shakeend', animate('1000ms ease-in',     keyframes([
              style({transform: 'translate3d(-1px, 0, 0)', offset: 0.1}),
              style({transform: 'translate3d(2px, 0, 0)', offset: 0.2}),
              style({transform: 'translate3d(-4px, 0, 0)', offset: 0.3}),
              style({transform: 'translate3d(4px, 0, 0)', offset: 0.4}),
              style({transform: 'translate3d(-4px, 0, 0)', offset: 0.5}),
              style({transform: 'translate3d(4px, 0, 0)', offset: 0.6}),
              style({transform: 'translate3d(-4px, 0, 0)', offset: 0.7}),
              style({transform: 'translate3d(2px, 0, 0)', offset: 0.8}),
              style({transform: 'translate3d(-1px, 0, 0)', offset: 0.9}),
            ]))),
      ])]
    })
    export class AppComponent  {
      states = {};
    
      constructor() {
        this.states['state1'] = 'shakestart';
        this.states['state2'] = 'shakestart';
      }
    
      shakeMe(stateVar: string) {
            this.states[stateVar] = (this.states[stateVar] === 'shakestart' ? 'shakeend' : 'shakestart');
      }
    
      shakeEnd(stateVar: string, event) {
        this.states[stateVar] = 'shakeend';
      }
    }
    

    You see, I use a dictionary for the animation states of the different html elements. Therefore, it is a little bit more work and overhead if you want to use Angular 6. shakeMe method starts the animation.

    However, I would recommend to just use CSS keyframes because it is easier to realize for several html elements. The following example does the same animation. You just have to apply the correct css class to the html element.

    .shakeit:hover {
        animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both;
        transform: translate3d(0, 0, 0);
        backface-visibility: hidden;
        perspective: 1000px;
    }
    
    @keyframes shake {
        10%, 90% {
            transform: translate3d(-1px, 0, 0);
        }
    
        20%, 80% {
            transform: translate3d(2px, 0, 0);
        }
    
        30%, 50%, 70% {
            transform: translate3d(-4px, 0, 0);
        }
    
        40%, 60% {
            transform: translate3d(4px, 0, 0);
        }
    }
    <h2 class="shakeit">Hover me</h2>