Mastering Angular Animations v7+
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/5075430/3qUVl6M-_400x400__1_.jpg)
Mastering Angular Animations v7+
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4407635/DIbT79QVYAAWrU4-magic.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4155401/angular-summit.gif)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/2756726/angular_high.png)
Gerard Sans
@gerardsans
Gerard Sans
@gerardsans
SANS
GERARD
Google Developer Expert
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4346612/1_2xKLZ6w42ujjp4d4Be6X6g2-magic__1_.png)
Google Developer Expert
International Speaker
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4026400/6df7410fac6d0d2822d92d59484ba2d9.jpg)
Spoken at 111 events in 27 countries
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4348163/Screen_Shot_2017-10-07_at_13.19.24.png)
Blogger
Blogger
Community Leader
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3077823/28311378825_756a12f091_o.jpg)
900
1.6K
Trainer
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3077765/1-Kt1ieFXLC8wuwm-wt0sziQ__1_.jpeg)
Master of Ceremonies
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4594092/DVCZ_0DXUAAkV36.jpg)
Master of Ceremonies
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/5148474/42438462475_82a8a02e52_o.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/5148473/WhatsApp_Image_2018-07-11_at_22.59.28.jpeg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/5148491/43288955442_03e46344fa_o.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3091031/Screen_Shot_2016-10-07_at_23.15.32.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3915020/DBE04UbXsAMwmzU.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3915021/34859725642_2cb24ea247_z.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3915023/34636330390_50c844e8ac_z.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3915056/35076212125_bbe45642dd_z.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3915058/34912260892_046f2f4874_z.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3915061/34688875100_abdbfb8741_z.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/5347703/Screen_Shot_2018-10-10_at_15.33.08.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/5347712/_gerardsans__1_.png)
#cfpwomen
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/5347748/Dc79AkJXcAAOmwn.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/5347813/Screen_Shot_2018-10-10_at_16.19.51.png)
Why introduce motion?
Improved UX ✨
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4082024/ezgif.com-resize__3_.gif)
Perceived Performance
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4089115/ezgif.com-gif-maker__4_.gif)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4089115/ezgif.com-gif-maker__4_.gif)
Immersive interactions
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4082209/apple-tv-poster__1_.gif)
Better engagement
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4082189/bootup_final_preview_1loop.gif)
User happiness 😃
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4082192/twitter_heart.gif)
Animation Principles
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4032214/3.jpg)
Squash & Stretch + Anticipation
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4032268/ezgif.com-video-to-gif__11_.gif)
Follow through
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4032278/ezgif.com-video-to-gif__12_.gif)
Exaggeration
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4032293/ezgif.com-video-to-gif__13_.gif)
Composition
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4032304/ezgif.com-video-to-gif__14_.gif)
Motion Design
Principles
Easing
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4033549/ezgif.com-video-to-gif__17_.gif)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4033575/ezgif.com-video-to-gif__20_.gif)
Offset Delay
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4033629/ezgif.com-video-to-gif__22_.gif)
Parenting
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4033635/ezgif.com-video-to-gif__23_.gif)
Binding Values
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4033639/ezgif.com-video-to-gif__24_.gif)
Overlay
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4033640/ezgif.com-video-to-gif__25_.gif)
CSS Transitions
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3766733/partyparrot.png)
DURATION
opacity: 0;
opacity: 1;
CSS Transitions
PROPERTY
transition: opacity 1s ease-in 1s;
DURATION
TIMING
DELAY
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3766733/partyparrot.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3766733/partyparrot.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3766733/partyparrot.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3766733/partyparrot.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3766733/partyparrot.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3766733/partyparrot.png)
timing function/easing
Fade
<div class="container">
<div class="circle base elastic"></div>
</div>
.circle {
border-radius: 50%;
position: absolute; opacity:0;
will-change: opacity, transform;
}
.base {
transition: opacity 1s ease,
transform 1s ease;
}
.elastic {
transition-timing-function:
cubic-bezier(.8,-0.6,0.2,1.5);
}
.container:hover .circle {
transform: translateX(80px);
opacity:1;
}
Fade
Animatable CSS
all background* border* bottom box-shadow clip clip-path color filter font* height left margin* mask* offset* opacity outline* padding* perspective* right text-decoration text-shadow top transform vertical-align visibility width z-index
CSS Animations
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3766733/partyparrot.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3766733/partyparrot.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3766733/partyparrot.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3766733/partyparrot.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3766733/partyparrot.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3766733/partyparrot.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3766733/partyparrot.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3766733/partyparrot.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/3766733/partyparrot.png)
DURATION
CSS Animations
0%
100%
KEYFRAMES
NAME
animation: fade 1s 1s infinite linear;
DURATION
DELAY
ITERATIONS
TIMING
Fade
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4033580/ezgif.com-video-to-gif__21_.gif)
<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;
}
}
Animations Performance
60 FPS
Smooth 60FPS
60 FPS
Time
16.66ms
16.66ms
16.66ms
1000/60ms
paint
frame
paint
frame
paint
frame
😃
paint
frame
paint
frame
Losing Frames!
60 FPS
Time
16.66ms
16.66ms
16.66ms
😱
Motion Techniques
Move
transform: translateX(10px);
Resize
transform: scale(0.5);
Rotate
transform: rotate(1turn);
Fade
opacity: 0;
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4033575/ezgif.com-video-to-gif__20_.gif)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4033558/ezgif.com-crop.gif)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4033570/ezgif.com-video-to-gif__19_.gif)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4033580/ezgif.com-video-to-gif__21_.gif)
Move
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4033575/ezgif.com-video-to-gif__20_.gif)
<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
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4033558/ezgif.com-crop.gif)
<div class="square base linear"></div>
.base {
animation: spin 2s infinite;
}
.linear {
animation-timing-function: linear;
}
@keyframes spin {
to {
transform: rotate(1turn);
}
}
Resize
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4033570/ezgif.com-video-to-gif__19_.gif)
<div class="circle base"></div>
.base {
animation: size 2s infinite;
}
@keyframes size {
0%, 40%, 100% {
transform: scale(1);
}
25%, 60% {
transform: scale(1.1);
}
}
Angular Animations
States & Transitions
fadeIn
fadeOut
Fading animation
TRANSITIONS
STATE
STATE
fadeIn => fadeOut
fadeOut => fadeIn
opacity: 1
opacity: 0
animate('400ms linear')
animate('400ms linear')
fadeOut <=> fadeIn
animate('400ms linear')
Fading an Element
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';
}
}
Fading Animation
import {
trigger, transition, state, style, animate
} from '@angular/animations';
export const fade = trigger('fade', [
state('fadeIn', style({ opacity: 1 })),
state('fadeOut', style({ opacity: 0 })),
transition('fadeIn <=> fadeOut', animate('400ms linear'))
]);
Applying
Motion
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4026556/Idea_ExplainerVideo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4026557/Brainstorm_ExplainerVideo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4026553/Storyboard_ExplainerVideo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4026484/60ea1674d2a2221937f5171f21aec302.gif)
Example
Adding Motion
void
*
Animating new items
void => *
STATE
STATE
:enter
scale(1)
opacity 1
scale(0.5)
opacity 0
*
void
Animating removed items
* => void
STATE
STATE
:leave
scale(0.5)
opacity 0
scale(1)
opacity 1
Execution Order
sequence
group
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
Composition
animateChild
time
Stagger
time
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
Dynamic Animations
Builder
`(${x}, ${y})`
(100, 50)
Player
Template
1
2
(100, 50)
3
build()
play()
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$ = fromEvent(document, 'mousemove')
.pipe(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();
}
})
}
More
Influencers
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4034523/89UyDWne_400x400.jpeg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4034524/97cssCek_400x400.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4034516/RwwbnNpi_400x400.jpg)
David Khourshid
Issara Willenskomer
Sarah Drasner
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4034536/DEePSp-XgAEEttj.jpg)
Rachel Nabors
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4033716/Screen_Shot_2017-08-07_at_02.58.20.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4082032/Screen_Shot_2017-08-30_at_02.32.15.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4407635/DIbT79QVYAAWrU4-magic.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/4155401/angular-summit.gif)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/345677/images/2756726/angular_high.png)
Mastering Angular Animations (v7+)
By Gerard Sans
Mastering Angular Animations (v7+)
How we can use Animations in Angular. 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!
- 3,421