slides.com/gerardsans |  @gerardsans

Reactive

Animations

Google Developer Expert

Master of Ceremonies

Blogger

International Speaker

Spoken at 56 events in 18 countries

Angular Trainer

Community Leader

900

1K

Angular In Flip Flops

#dfua

Why use Animations?

Improved UX

Perceived Performance

Immersive interactions

Better engagement

User happiness 😃

Animation Principles

Squash & Stretch + Anticipation

Follow through

Exaggeration

Composition

Animation Techniques

Move

transform: translateX(10px);

Resize

transform: scale(0.5);

Rotate

transform: rotate(1turn);

Fade

opacity: 0;

Move

<div class="circle base elastic"></div>

.base {
  animation: move 2s infinite;
}
.elastic { 
  animation-timing-function: 
    cubic-bezier(.8,-0.6,0.2,1.5);
}

@keyframes move {
  0% { 
    transform: translateX(-250px);
  }
  40%, 60% { 
    transform: translateX(50px);
  }
  100% { 
    transform: translateX(250px);
  }
}

Rotate

<div class="square base linear"></div>

.base {
  animation: spin 2s infinite;
}
.linear {
  animation-timing-function: linear;
}

@keyframes spin {
  to { 
    transform: rotate(1turn);
  }
}

Resize

<div class="circle base"></div>

.base {
  animation: size 2s infinite;
}

@keyframes size {
  0%, 40%, 100% {
    transform: scale(1);
  }
  25%, 60% {
    transform: scale(1.1);
  }
}

Fade

<div class="circle base elastic"></div>

.base {
  animation: fade 2s infinite;
}

@keyframes fade {
  0% { 
    transform: translateX(0px);
    opacity: 0;
  }
  40%, 60% { 
    transform: translateX(80px);
    opacity: 1;
  }
  100% { 
    transform: translateX(0px);
    opacity: 0;
  }
}

Advanced Techniques

Easing

Offset Delay

Parenting

Binding Values

Overlay

Example

Angular Animations

States & Transitions

void

*

Special Keywords

void => *           :enter

* => void          :leave

void <=> *

STATE

STATE

fadeIn

fadeOut

States & Transitions

TRANSITIONS

STATE

STATE

fadeIn => fadeOut

fadeOut => fadeIn

fadeIn <=> fadeOut

Animation Example

import {fade} from './animations';

@Component({
  selector: 'my-app',
  template: `<button [@fade]='fade' (click)="toggleFade()">Fade</button>`,
  animations: [ fade ]
})
export class App {
  fade = 'fadeIn';
  toggleFade(){
    this.fade = this.fade === 'fadeIn' ? 'fadeOut' : 'fadeIn';
  }
}

Animation Example

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

export const fade = trigger('fade', [
  state('fadeIn', style({ opacity: 1 })),
  state('fadeOut', style({ opacity: 0.1 })),
  transition('fadeIn <=> fadeOut', animate('2000ms linear'))
]);

Execution Order

sequence

group

time

Composition

animateChild

time

Stagger

time

Dynamic Selectors

class="container"

class="item"

class="item"

query(selector)

Dynamic Selectors

query('.item')

class="container"

class="item"

class="item"

Dynamic Selectors

query('.item:enter')

class="container"

class="item"

class="item"

class="item"

added

Reactive Animations

Introduction

  • react to user interactions
  • maps user input to CSS
    • mouse position, keyboard, scroll, input field
  • static or dynamic

Technologies

  • Animations
    • CSS, canvas, WebGL, SVG
  • AnimationBuilder
    • Player
  • Events
    • RxJS

AnimationBuilder

import {AnimationBuilder} from "@angular/animations";
export class MyComponent {
  constructor(
    private elem: ElementRef, 
    private builder: AnimationBuilder
  ) {
    const player = this.playerMoveTo({ x: 100, y: 100 });
    player.play();
  } 
  playerMoveTo(to) {
    const moveAnimation = this.builder.build([
      animate('1s', style({ transform: `translate(${x}px, ${y}px)` }))
    ]);
    return moveAnimation.create(this.elem.nativeElement
      , {params: { x: to.x, y: to.y }});
  }
}

Tracking mouse position

constructor(
  private elem: ElementRef
) {
  // find out center
  this.mx = elem.nativeElement.offsetWidth/2;
  this.my = elem.nativeElement.offsetHeight/2;
} 

ngOnInit() {
  const mouseMove$ = Observable.fromEvent(document, 'mousemove')
    .map(e => ({ x: e.pageX, y: e.pageY }));

  mouseMove$.subscribe({
    next: e => {
      this.lastPosition = { x: e.x-this.mx, y: e.y-this.my };
      const player = this.playerMoveTo(this.lastPosition);
      player.play();
    }
  })
}

Performance

Considerations

  • Avoid unnecessary layout/repaint
    • Use opacity, transform
  • Hardware acceleration (avoid)
    • transform: translateZ(0)

Saving Resources

.visible.advert {
  will-change: transform;
}

.visible.advert:hover {
  transform: scale(1.2);
}

More

Inspiration

David Khourshid

Issara Willenskomer

Sarah Drasner

Rachel Nabors

Reactive Animations using Angular

By Gerard Sans

Reactive Animations using Angular

How we can use Angular to achieve Reactive Animations. The overall idea is capturing multiple streams of events into one, and then emitting those values over to CSS creating animations. We will cover Web Animations API and how we can use Angular together with field-tested animation techniques providing examples for CSS transitions/animations and SVG. We will also study browser compatibility and performance to achieve reliable and smooth animations. Let's bring our Angular skills to the awesome world of animations!

  • 2,980