SlideShare a Scribd company logo
1 of 41
Download to read offline
“I like to move it”
Anima&ng Angular Applica&ons
… but why?
‣ Expecta&on
‣ Con&nuity
‣ Narra&ve
‣ Rela&onship







https://medium.com/ux-in-motion/creating-usability-
with-motion-the-ux-in-motion-manifesto-a87a4584ddc
User Experience experts say:
@sulco
Tomek Sułkowski
engineer @ fourTheorem and @ StackBlitz trainer
declara3ve impera3ve
declara3ve impera3ve
basics
Setup
import {
BrowserAnimationsModule
} from '@angular/platform-browser/animations';
@NgModule({
imports: [
BrowserAnimationsModule,
]
})
export class AppModule { }
Just use BrowserAnimationsModule
Setup
import {
BrowserAnimationsModule
} from '@angular/platform-browser/animations';
@NgModule({
imports: [
BrowserAnimationsModule,
]
})
export class AppModule { }
Just use BrowserAnimationsModule
NoopAnimationsModule
for tests
Seman3cs
Trigger
func&on linking anima&on with a specific
element (i.e. an “anchor” for anima&on)


State
descrip&on of style in a discrete moment


Transi3on
descrip&on of the way styles change from
one state to another
Angular anima&ons nomenclature
state:
“on”
state:
“off”
trigger: @myFade
Implementa3on
trigger('myFade', []);
import { …stuff… } from ‘@angular/anima&ons’
state:
“on”
state:
“off”
trigger: @myFade
Implementa3on
trigger('myFade', [
state('on', style({opacity: 1.0})),
state('off', style({opacity: 0.3})),
]);
import { …stuff… } from ‘@angular/anima&ons’
state:
“on”
state:
“off”
trigger: @myFade
Implementa3on
trigger('myFade', [
state('on', style({opacity: 1.0})),
state('off', style({opacity: 0.3})),
transition('on !=> off', animate('300ms ease-in')),
transition('off !=> on', animate('100ms ease-in')),
]);
import { …stuff… } from ‘@angular/anima&ons’
state:
“on”
state:
“off”
trigger: @myFade
300ms
100ms
Implementa3on
trigger('myFade', [
state('on', style({opacity: 1.0})),
state('off', style({opacity: 0.3})),
transition('on !=> off’,
'off !=> on', animate('300ms ease-in')),
]);
import { …stuff… } from ‘@angular/anima&ons’
state:
“on”
state:
“off”
trigger: @myFade
300ms
300ms
Implementa3on
trigger('myFade', [
state('on', style({opacity: 1.0})),
state('off', style({opacity: 0.3})),
transition('on !!<=> off', animate('300ms ease-in’)),
]);
import { …stuff… } from ‘@angular/anima&ons’
state:
“on”
state:
“off”
trigger: @myFade
300ms
300ms
Implementa3on
trigger('myFade', [
state('on', style({opacity: 1.0})),
state('off', style({opacity: 0.3})),
transition(‘* !!<=> *’, animate('300ms ease-in’)),
]);
import { …stuff… } from ‘@angular/anima&ons’
state:
“on”
state:
“off”
trigger: @myFade
300ms
300ms
state:
“!!...”
300ms
Implementa3on
trigger('myFade', [
state('on', style({opacity: 1.0})),
state('off', style({opacity: 0.3})),
transition('void !=> *', animate('300ms')),
transition('* !=> void', animate('100ms')),
]);
transition(‘:enter', animate('300ms')),
transition(':leave', animate(‘100ms')),
import { …stuff… } from ‘@angular/anima&ons’
state:
“on”




void
trigger: @myFade




void
Usage
<div
[@myFade]="myState"
(click)="myState ""=== 'off' ? 'on' : 'off'"
>
Click me
"</div>
“@” - yet another symbol in Angular templates
@Component({
animations: [
trigger('myFade', [....])
]
})
state:
“on”
state:
“off”
trigger: @myFade
300ms
100ms
Usage
<div
[@myFade]="myState"
(click)="myState ""=== 'off' ? 'on' : 'off'"
>
Click me
!</div>
“@” - yet another symbol in Angular templates
@Component({
animations: [
trigger('myFade', [....])
]
})
state:
“on”
state:
“off”
trigger: @myFade
300ms
100ms
Usage
<div
[@myFade]="myState"
(click)="myState ""=== 'off' ? 'on' : 'off'"
(@myFade.start)="handleStart($event)"
(@myFade.done)="handleDone($event)"
>
Click me
!</div>
Callbacks (“let me know when you…”)
state:
“on”
state:
“off”
trigger: @myFade
300ms
100ms
Usage
<div
[@myFade]="myState"
(click)="myState ""=== 'off' ? 'on' : 'off'"
(@myFade.start)="handleStart($event)"
(@myFade.done)="handleDone($event)"
>
Click me
!</div>
Callbacks (“let me know when you…”)
state:
“on”
state:
“off”
trigger: @myFade
300ms
100ms
interface AnimationEvent {
fromState: string
toState: string
totalTime: number
phaseName: string
element: any
triggerName: string
disabled: boolean
}
staggering
Seman3cs 102
Query
select elements (inside a trigger)
that match a query token


Stagger
a series of anima&ons applied to subsequent
found element with a delay between them
Some more anima&on nomenclature <div>"</div>
trigger: @myStagger
<div>"</div>
<div>"</div>
:enter
.item
@*
<div>"</div>
<div>"</div>
<div>"</div>
examples of query tokens:
- anima&on keyword
- css selector
- trigger name
Implementa3on
<div [@myStagger]="items.length">
<div *ngFor="let item of items">
{{ item }}
"</div>
"</div>
<div>"</div>
trigger: @myStagger
<div>"</div>
<div>"</div>
<div>"</div>
<div>"</div>
<div>"</div>
Implementa3on
<div [@myStagger]="items.length">
<div *ngFor="let item of items">
{{ item }}
"</div>
"</div>
<div>"</div>
trigger: @myStagger
<div>"</div>
<div>"</div>
<div>"</div>
<div>"</div>
<div>"</div>
trigger('listAnimation', [
transition('* "=> *', [
query(':leave', [
stagger(100, [
animate('0.5s', style({ opacity: 0 }))
])
]),
query(':enter', [
style({ opacity: 0 }),
stagger(100, [
animate('0.5s', style({ opacity: 1 }))
])
])
])
])
Implementa3on
<div [@myStagger]="items.length">
<div *ngFor="let item of items">
{{ item }}
"</div>
"</div>
<div>"</div>
trigger: @myStagger
<div>"</div>
<div>"</div>
<div>"</div>
<div>"</div>
<div>"</div>
trigger('listAnimation', [
transition('* "=> *', [
query(':leave', [
stagger(100, [
animate('0.5s', style({ opacity: 0 }))
])
]),
query(':enter', [
style({ opacity: 0 }),
stagger(100, [
animate('0.5s', style({ opacity: 1 }))
])
])
])
])
router

anima3on
Implementa3on
<RouterOutlet>
is a direc&ve (exportAs: “outlet”) with
activatedRoute & activatedRouteData
proper&es
<main [@routerAnim]="getState(outletRef)">
<router-outlet #outletRef=“outlet”>
"</router-outlet>
"</main>
We can use this to get a state value
for an anima&on trigger.
getState(outletRef: RouterOutlet) {
return outletRef.activatedRouteData.name;
}
Implementa3on
trigger('routerTransition', [
transition('* ""<=> *', [
group([
query(':enter', [
style({transform: 'translateX(100%)'}),
animate('0.4s ease-in-out’,
style({transform: 'translateX(0%)'}))
], {optional: true}),
query(':leave', [
style({transform: 'translateX(0%)'}),
animate('0.4s ease-in-out’,
style({transform: ‘translateX(100%)'}))
], {optional: true}),
]),
]),
])
Heads up!
Anima&ons within the same route
won’t work by default.
@NgModule({
imports: [RouterModule.forRoot(routes)],
providers: [{
provide: RouteReuseStrategy,
useClass: CustomReuseStrategy
}],
})
export class CustomReuseStrategy implements RouteReuseStrategy {
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return curr.component ""!== MyFruitComponent;
}
… (see the full class)
Heads up!
Anima&ons within the same route
won’t work by default.
@NgModule({
imports: [RouterModule.forRoot(routes)],
providers: [{
provide: RouteReuseStrategy,
useClass: CustomReuseStrategy
}],
})
export class CustomReuseStrategy implements RouteReuseStrategy {
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return curr.component ""!== MyFruitComponent;
}
… (see the full class)
Heads up!
Anima&ons within the same route
won’t work by default.
@NgModule({
imports: [RouterModule.forRoot(routes)],
providers: [{
provide: RouteReuseStrategy,
useClass: CustomReuseStrategy
}],
})
export class CustomReuseStrategy implements RouteReuseStrategy {
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return curr.component ""!== MyFruitComponent;
}
… (see the full class)
declara3ve impera3ve
Anima3onBuilder
Anima3onBuilder
with the build() method creates
a configured Anima&onFactory


Anima3onFactory
with the create() method creates
an Anima&onPlayer
Anima3onPlayer
allows to control the anima&on
like FormBuilder… but for anima&ons
Anima3onBuilder
const factory = this.animBuilder.build([
]);
this.player = factory.create(this.containerRef.nativeElement);
this.player.play();
this.player.onDone(() "=> resolve());
query(tilesQuery, style({ transform: 'translate3d(0, 0, 0)' }), { optional }),
query(
tilesQuery,
stagger(50, [
animate('900ms’,style({ transform: 'rotateX(180deg)' })),
]),
{ optional },
),
query(tilesQuery, style({ transform: 'translate3d(0, 0, 0)' }), { optional }),
query(
tilesQuery,
stagger(50, [
animate('900ms’,style({ transform: 'rotateX(180deg)' })),
]),
{ optional },
),
Anima3onBuilder
const factory = this.animBuilder.build([
]);
this.player = factory.create(this.containerRef.nativeElement);
this.player.play();
this.player.onDone(() "=> resolve());
Anima3onBuilder
const factory = this.animBuilder.build([
query(tilesQuery, style({ transform: 'translate3d(0, 0, 0)' }), { optional }),
query(
tilesQuery,
stagger(50, [
animate('900ms’,style({ transform: 'rotateX(180deg)' })),
]),
{ optional },
),
]);
this.player = factory.create(this.containerRef.nativeElement);
this.player.play();
this.player.onDone(() "=> resolve());
Actually…
Anima3onBuilder
const factory = this.animBuilder.build([
query(tilesQuery, style({ transform: 'translate3d(0, 0, 0)' }), { optional }),
query(
tilesQuery,
stagger(50, [
animate('900ms’,style({ transform: 'rotateX(180deg)' })),
]),
{ optional },
),
]);
this.player = factory.create(this.containerRef.nativeElement);
this.player.play();
this.player.onDone(() "=> resolve());
RxJS + Web Anima3ons API
const animationOptions = { duration: 900, fill: ‘forwards' }
const keyframes = [
{ transform: 'translate3d(0, 0, 0)' },
{ transform: 'rotateX(180deg)' }
];
return timer(0, 50, animationFrame)
.pipe(
take(tiles.length),
map(i "=> tiles[i].animate(keyframes, this.animationOptions)),
reduce((anims, anim) "=> [""...anims, anim], []),
delay(this.animationOptions.duration),
tap(anims "=> anims.forEach(anim "=> anim.cancel())),
);
teraz nie zapomnij pokazać dema :p
More on anima&ons
‣ Angular in Mo&on: 4 approaches to anima&on
‣ Angular Router Anima&ons - what they don't tell you
Ok, cheers!
h`ps://twi`er.com/sulco

More Related Content

What's hot

Academy PRO: React native - building first scenes
Academy PRO: React native - building first scenesAcademy PRO: React native - building first scenes
Academy PRO: React native - building first scenesBinary Studio
 
Android Camera Architecture
Android Camera ArchitectureAndroid Camera Architecture
Android Camera ArchitecturePicker Weng
 
Dirty Durham: Dry cleaning solvents leaked into part of Trinity Park | News
Dirty Durham: Dry cleaning solvents leaked into part of Trinity Park | NewsDirty Durham: Dry cleaning solvents leaked into part of Trinity Park | News
Dirty Durham: Dry cleaning solvents leaked into part of Trinity Park | Newsdizzyspiral5631
 
Enjoy the vue.js
Enjoy the vue.jsEnjoy the vue.js
Enjoy the vue.jsTechExeter
 
Modules and injector
Modules and injectorModules and injector
Modules and injectorEyal Vardi
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Chris Alfano
 
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...Codemotion
 
Ui perfomance
Ui perfomanceUi perfomance
Ui perfomanceCleveroad
 
Best Practices for Magento Debugging
Best Practices for Magento Debugging Best Practices for Magento Debugging
Best Practices for Magento Debugging varien
 
Yearning jQuery
Yearning jQueryYearning jQuery
Yearning jQueryRemy Sharp
 
Fixing Magento Core for Better Performance - Ivan Chepurnyi
Fixing Magento Core for Better Performance - Ivan ChepurnyiFixing Magento Core for Better Performance - Ivan Chepurnyi
Fixing Magento Core for Better Performance - Ivan ChepurnyiMeet Magento Spain
 
How to create a camera2
How to create a camera2How to create a camera2
How to create a camera2Booch Lin
 
Is HTML5 Ready? (workshop)
Is HTML5 Ready? (workshop)Is HTML5 Ready? (workshop)
Is HTML5 Ready? (workshop)Remy Sharp
 
AngularJS, More Than Directives !
AngularJS, More Than Directives !AngularJS, More Than Directives !
AngularJS, More Than Directives !Gaurav Behere
 
Responsive Web Design e a Ubiquidade da Web
Responsive Web Design e a Ubiquidade da WebResponsive Web Design e a Ubiquidade da Web
Responsive Web Design e a Ubiquidade da WebEduardo Shiota Yasuda
 
An Event Apart Boston: Principles of Unobtrusive JavaScript
An Event Apart Boston: Principles of Unobtrusive JavaScriptAn Event Apart Boston: Principles of Unobtrusive JavaScript
An Event Apart Boston: Principles of Unobtrusive JavaScriptPeter-Paul Koch
 
2010 bb dev con
2010 bb dev con 2010 bb dev con
2010 bb dev con Eing Ong
 
JSLab. Алексей Волков. "React на практике"
JSLab. Алексей Волков. "React на практике"JSLab. Алексей Волков. "React на практике"
JSLab. Алексей Волков. "React на практике"GeeksLab Odessa
 

What's hot (20)

Academy PRO: React native - building first scenes
Academy PRO: React native - building first scenesAcademy PRO: React native - building first scenes
Academy PRO: React native - building first scenes
 
Android Camera Architecture
Android Camera ArchitectureAndroid Camera Architecture
Android Camera Architecture
 
Dirty Durham: Dry cleaning solvents leaked into part of Trinity Park | News
Dirty Durham: Dry cleaning solvents leaked into part of Trinity Park | NewsDirty Durham: Dry cleaning solvents leaked into part of Trinity Park | News
Dirty Durham: Dry cleaning solvents leaked into part of Trinity Park | News
 
Enjoy the vue.js
Enjoy the vue.jsEnjoy the vue.js
Enjoy the vue.js
 
Modules and injector
Modules and injectorModules and injector
Modules and injector
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011
 
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
 
Ui perfomance
Ui perfomanceUi perfomance
Ui perfomance
 
Best Practices for Magento Debugging
Best Practices for Magento Debugging Best Practices for Magento Debugging
Best Practices for Magento Debugging
 
Yearning jQuery
Yearning jQueryYearning jQuery
Yearning jQuery
 
Fixing Magento Core for Better Performance - Ivan Chepurnyi
Fixing Magento Core for Better Performance - Ivan ChepurnyiFixing Magento Core for Better Performance - Ivan Chepurnyi
Fixing Magento Core for Better Performance - Ivan Chepurnyi
 
How to create a camera2
How to create a camera2How to create a camera2
How to create a camera2
 
Is HTML5 Ready? (workshop)
Is HTML5 Ready? (workshop)Is HTML5 Ready? (workshop)
Is HTML5 Ready? (workshop)
 
Images and PWA in magento
Images and PWA in magentoImages and PWA in magento
Images and PWA in magento
 
AngularJS, More Than Directives !
AngularJS, More Than Directives !AngularJS, More Than Directives !
AngularJS, More Than Directives !
 
Responsive Web Design e a Ubiquidade da Web
Responsive Web Design e a Ubiquidade da WebResponsive Web Design e a Ubiquidade da Web
Responsive Web Design e a Ubiquidade da Web
 
An Event Apart Boston: Principles of Unobtrusive JavaScript
An Event Apart Boston: Principles of Unobtrusive JavaScriptAn Event Apart Boston: Principles of Unobtrusive JavaScript
An Event Apart Boston: Principles of Unobtrusive JavaScript
 
2010 bb dev con
2010 bb dev con 2010 bb dev con
2010 bb dev con
 
Mgd08 lab01
Mgd08 lab01Mgd08 lab01
Mgd08 lab01
 
JSLab. Алексей Волков. "React на практике"
JSLab. Алексей Волков. "React на практике"JSLab. Алексей Волков. "React на практике"
JSLab. Алексей Волков. "React на практике"
 

Similar to Animating angular applications

Private slideshow
Private slideshowPrivate slideshow
Private slideshowsblackman
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010Fabien Potencier
 
Europython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & CeleryEuropython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & CeleryMauro Rocco
 
Visual Component Testing -- w/ Gil Tayar (Applitools) and Gleb Bahmutov (Cyp...
Visual Component Testing  -- w/ Gil Tayar (Applitools) and Gleb Bahmutov (Cyp...Visual Component Testing  -- w/ Gil Tayar (Applitools) and Gleb Bahmutov (Cyp...
Visual Component Testing -- w/ Gil Tayar (Applitools) and Gleb Bahmutov (Cyp...Applitools
 
Mobile HTML, CSS, and JavaScript
Mobile HTML, CSS, and JavaScriptMobile HTML, CSS, and JavaScript
Mobile HTML, CSS, and JavaScriptfranksvalli
 
Angular2: Quick overview with 2do app example
Angular2: Quick overview with 2do app exampleAngular2: Quick overview with 2do app example
Angular2: Quick overview with 2do app exampleAlexey Frolov
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsFrancois Zaninotto
 
A re introduction to webpack - reactfoo - mumbai
A re introduction to webpack - reactfoo - mumbaiA re introduction to webpack - reactfoo - mumbai
A re introduction to webpack - reactfoo - mumbaiPraveen Puglia
 
Exploring Angular 2 - Episode 2
Exploring Angular 2 - Episode 2Exploring Angular 2 - Episode 2
Exploring Angular 2 - Episode 2Ahmed Moawad
 
[22]Efficient and Testable MVVM pattern
[22]Efficient and Testable MVVM pattern[22]Efficient and Testable MVVM pattern
[22]Efficient and Testable MVVM patternNAVER Engineering
 
준비하세요 Angular js 2.0
준비하세요 Angular js 2.0준비하세요 Angular js 2.0
준비하세요 Angular js 2.0Jeado Ko
 
Jan 2017 - a web of applications (angular 2)
Jan 2017 - a web of applications (angular 2)Jan 2017 - a web of applications (angular 2)
Jan 2017 - a web of applications (angular 2)Kasper Reijnders
 
8 things you didn't know about the Angular Router, you won't believe #6!
8 things you didn't know about the Angular Router, you won't believe #6!8 things you didn't know about the Angular Router, you won't believe #6!
8 things you didn't know about the Angular Router, you won't believe #6!Laurent Duveau
 
Svg, canvas e animations in angular (3 maggio 2019)
Svg, canvas e animations in angular (3 maggio 2019)Svg, canvas e animations in angular (3 maggio 2019)
Svg, canvas e animations in angular (3 maggio 2019)Leonardo Buscemi
 
Seven Peaks Speaks - Compose Screenshot Testing Made Easy
Seven Peaks Speaks - Compose Screenshot Testing Made EasySeven Peaks Speaks - Compose Screenshot Testing Made Easy
Seven Peaks Speaks - Compose Screenshot Testing Made EasySeven Peaks Speaks
 
Compose로 Android:Desktop 멀티플랫폼 만들기.pdf
Compose로 Android:Desktop 멀티플랫폼 만들기.pdfCompose로 Android:Desktop 멀티플랫폼 만들기.pdf
Compose로 Android:Desktop 멀티플랫폼 만들기.pdfssuserb6c2641
 

Similar to Animating angular applications (20)

Private slideshow
Private slideshowPrivate slideshow
Private slideshow
 
Clean Javascript
Clean JavascriptClean Javascript
Clean Javascript
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010
 
Frontin like-a-backer
Frontin like-a-backerFrontin like-a-backer
Frontin like-a-backer
 
Europython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & CeleryEuropython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & Celery
 
Visual Component Testing -- w/ Gil Tayar (Applitools) and Gleb Bahmutov (Cyp...
Visual Component Testing  -- w/ Gil Tayar (Applitools) and Gleb Bahmutov (Cyp...Visual Component Testing  -- w/ Gil Tayar (Applitools) and Gleb Bahmutov (Cyp...
Visual Component Testing -- w/ Gil Tayar (Applitools) and Gleb Bahmutov (Cyp...
 
Nativescript angular
Nativescript angularNativescript angular
Nativescript angular
 
Mobile HTML, CSS, and JavaScript
Mobile HTML, CSS, and JavaScriptMobile HTML, CSS, and JavaScript
Mobile HTML, CSS, and JavaScript
 
Angular2: Quick overview with 2do app example
Angular2: Quick overview with 2do app exampleAngular2: Quick overview with 2do app example
Angular2: Quick overview with 2do app example
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
 
A re introduction to webpack - reactfoo - mumbai
A re introduction to webpack - reactfoo - mumbaiA re introduction to webpack - reactfoo - mumbai
A re introduction to webpack - reactfoo - mumbai
 
Exploring Angular 2 - Episode 2
Exploring Angular 2 - Episode 2Exploring Angular 2 - Episode 2
Exploring Angular 2 - Episode 2
 
[22]Efficient and Testable MVVM pattern
[22]Efficient and Testable MVVM pattern[22]Efficient and Testable MVVM pattern
[22]Efficient and Testable MVVM pattern
 
준비하세요 Angular js 2.0
준비하세요 Angular js 2.0준비하세요 Angular js 2.0
준비하세요 Angular js 2.0
 
Jan 2017 - a web of applications (angular 2)
Jan 2017 - a web of applications (angular 2)Jan 2017 - a web of applications (angular 2)
Jan 2017 - a web of applications (angular 2)
 
8 things you didn't know about the Angular Router, you won't believe #6!
8 things you didn't know about the Angular Router, you won't believe #6!8 things you didn't know about the Angular Router, you won't believe #6!
8 things you didn't know about the Angular Router, you won't believe #6!
 
Svg, canvas e animations in angular (3 maggio 2019)
Svg, canvas e animations in angular (3 maggio 2019)Svg, canvas e animations in angular (3 maggio 2019)
Svg, canvas e animations in angular (3 maggio 2019)
 
Seven Peaks Speaks - Compose Screenshot Testing Made Easy
Seven Peaks Speaks - Compose Screenshot Testing Made EasySeven Peaks Speaks - Compose Screenshot Testing Made Easy
Seven Peaks Speaks - Compose Screenshot Testing Made Easy
 
Compose로 Android:Desktop 멀티플랫폼 만들기.pdf
Compose로 Android:Desktop 멀티플랫폼 만들기.pdfCompose로 Android:Desktop 멀티플랫폼 만들기.pdf
Compose로 Android:Desktop 멀티플랫폼 만들기.pdf
 
Applets
AppletsApplets
Applets
 

Recently uploaded

What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfPower Karaoke
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 

Recently uploaded (20)

Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdf
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 

Animating angular applications

  • 1. “I like to move it” Anima&ng Angular Applica&ons
  • 2. … but why? ‣ Expecta&on ‣ Con&nuity ‣ Narra&ve ‣ Rela&onship
 
 
 
 https://medium.com/ux-in-motion/creating-usability- with-motion-the-ux-in-motion-manifesto-a87a4584ddc User Experience experts say:
  • 3. @sulco Tomek Sułkowski engineer @ fourTheorem and @ StackBlitz trainer
  • 7. Setup import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; @NgModule({ imports: [ BrowserAnimationsModule, ] }) export class AppModule { } Just use BrowserAnimationsModule
  • 8. Setup import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; @NgModule({ imports: [ BrowserAnimationsModule, ] }) export class AppModule { } Just use BrowserAnimationsModule NoopAnimationsModule for tests
  • 9. Seman3cs Trigger func&on linking anima&on with a specific element (i.e. an “anchor” for anima&on) 
 State descrip&on of style in a discrete moment 
 Transi3on descrip&on of the way styles change from one state to another Angular anima&ons nomenclature state: “on” state: “off” trigger: @myFade
  • 10. Implementa3on trigger('myFade', []); import { …stuff… } from ‘@angular/anima&ons’ state: “on” state: “off” trigger: @myFade
  • 11. Implementa3on trigger('myFade', [ state('on', style({opacity: 1.0})), state('off', style({opacity: 0.3})), ]); import { …stuff… } from ‘@angular/anima&ons’ state: “on” state: “off” trigger: @myFade
  • 12. Implementa3on trigger('myFade', [ state('on', style({opacity: 1.0})), state('off', style({opacity: 0.3})), transition('on !=> off', animate('300ms ease-in')), transition('off !=> on', animate('100ms ease-in')), ]); import { …stuff… } from ‘@angular/anima&ons’ state: “on” state: “off” trigger: @myFade 300ms 100ms
  • 13. Implementa3on trigger('myFade', [ state('on', style({opacity: 1.0})), state('off', style({opacity: 0.3})), transition('on !=> off’, 'off !=> on', animate('300ms ease-in')), ]); import { …stuff… } from ‘@angular/anima&ons’ state: “on” state: “off” trigger: @myFade 300ms 300ms
  • 14. Implementa3on trigger('myFade', [ state('on', style({opacity: 1.0})), state('off', style({opacity: 0.3})), transition('on !!<=> off', animate('300ms ease-in’)), ]); import { …stuff… } from ‘@angular/anima&ons’ state: “on” state: “off” trigger: @myFade 300ms 300ms
  • 15. Implementa3on trigger('myFade', [ state('on', style({opacity: 1.0})), state('off', style({opacity: 0.3})), transition(‘* !!<=> *’, animate('300ms ease-in’)), ]); import { …stuff… } from ‘@angular/anima&ons’ state: “on” state: “off” trigger: @myFade 300ms 300ms state: “!!...” 300ms
  • 16. Implementa3on trigger('myFade', [ state('on', style({opacity: 1.0})), state('off', style({opacity: 0.3})), transition('void !=> *', animate('300ms')), transition('* !=> void', animate('100ms')), ]); transition(‘:enter', animate('300ms')), transition(':leave', animate(‘100ms')), import { …stuff… } from ‘@angular/anima&ons’ state: “on” 
 
 void trigger: @myFade 
 
 void
  • 17. Usage <div [@myFade]="myState" (click)="myState ""=== 'off' ? 'on' : 'off'" > Click me "</div> “@” - yet another symbol in Angular templates @Component({ animations: [ trigger('myFade', [....]) ] }) state: “on” state: “off” trigger: @myFade 300ms 100ms
  • 18. Usage <div [@myFade]="myState" (click)="myState ""=== 'off' ? 'on' : 'off'" > Click me !</div> “@” - yet another symbol in Angular templates @Component({ animations: [ trigger('myFade', [....]) ] }) state: “on” state: “off” trigger: @myFade 300ms 100ms
  • 19. Usage <div [@myFade]="myState" (click)="myState ""=== 'off' ? 'on' : 'off'" (@myFade.start)="handleStart($event)" (@myFade.done)="handleDone($event)" > Click me !</div> Callbacks (“let me know when you…”) state: “on” state: “off” trigger: @myFade 300ms 100ms
  • 20. Usage <div [@myFade]="myState" (click)="myState ""=== 'off' ? 'on' : 'off'" (@myFade.start)="handleStart($event)" (@myFade.done)="handleDone($event)" > Click me !</div> Callbacks (“let me know when you…”) state: “on” state: “off” trigger: @myFade 300ms 100ms interface AnimationEvent { fromState: string toState: string totalTime: number phaseName: string element: any triggerName: string disabled: boolean }
  • 22. Seman3cs 102 Query select elements (inside a trigger) that match a query token 
 Stagger a series of anima&ons applied to subsequent found element with a delay between them Some more anima&on nomenclature <div>"</div> trigger: @myStagger <div>"</div> <div>"</div> :enter .item @* <div>"</div> <div>"</div> <div>"</div> examples of query tokens: - anima&on keyword - css selector - trigger name
  • 23. Implementa3on <div [@myStagger]="items.length"> <div *ngFor="let item of items"> {{ item }} "</div> "</div> <div>"</div> trigger: @myStagger <div>"</div> <div>"</div> <div>"</div> <div>"</div> <div>"</div>
  • 24. Implementa3on <div [@myStagger]="items.length"> <div *ngFor="let item of items"> {{ item }} "</div> "</div> <div>"</div> trigger: @myStagger <div>"</div> <div>"</div> <div>"</div> <div>"</div> <div>"</div> trigger('listAnimation', [ transition('* "=> *', [ query(':leave', [ stagger(100, [ animate('0.5s', style({ opacity: 0 })) ]) ]), query(':enter', [ style({ opacity: 0 }), stagger(100, [ animate('0.5s', style({ opacity: 1 })) ]) ]) ]) ])
  • 25. Implementa3on <div [@myStagger]="items.length"> <div *ngFor="let item of items"> {{ item }} "</div> "</div> <div>"</div> trigger: @myStagger <div>"</div> <div>"</div> <div>"</div> <div>"</div> <div>"</div> trigger('listAnimation', [ transition('* "=> *', [ query(':leave', [ stagger(100, [ animate('0.5s', style({ opacity: 0 })) ]) ]), query(':enter', [ style({ opacity: 0 }), stagger(100, [ animate('0.5s', style({ opacity: 1 })) ]) ]) ]) ])
  • 27. Implementa3on <RouterOutlet> is a direc&ve (exportAs: “outlet”) with activatedRoute & activatedRouteData proper&es <main [@routerAnim]="getState(outletRef)"> <router-outlet #outletRef=“outlet”> "</router-outlet> "</main> We can use this to get a state value for an anima&on trigger. getState(outletRef: RouterOutlet) { return outletRef.activatedRouteData.name; }
  • 28. Implementa3on trigger('routerTransition', [ transition('* ""<=> *', [ group([ query(':enter', [ style({transform: 'translateX(100%)'}), animate('0.4s ease-in-out’, style({transform: 'translateX(0%)'})) ], {optional: true}), query(':leave', [ style({transform: 'translateX(0%)'}), animate('0.4s ease-in-out’, style({transform: ‘translateX(100%)'})) ], {optional: true}), ]), ]), ])
  • 29. Heads up! Anima&ons within the same route won’t work by default. @NgModule({ imports: [RouterModule.forRoot(routes)], providers: [{ provide: RouteReuseStrategy, useClass: CustomReuseStrategy }], }) export class CustomReuseStrategy implements RouteReuseStrategy { shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { return curr.component ""!== MyFruitComponent; } … (see the full class)
  • 30. Heads up! Anima&ons within the same route won’t work by default. @NgModule({ imports: [RouterModule.forRoot(routes)], providers: [{ provide: RouteReuseStrategy, useClass: CustomReuseStrategy }], }) export class CustomReuseStrategy implements RouteReuseStrategy { shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { return curr.component ""!== MyFruitComponent; } … (see the full class)
  • 31. Heads up! Anima&ons within the same route won’t work by default. @NgModule({ imports: [RouterModule.forRoot(routes)], providers: [{ provide: RouteReuseStrategy, useClass: CustomReuseStrategy }], }) export class CustomReuseStrategy implements RouteReuseStrategy { shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { return curr.component ""!== MyFruitComponent; } … (see the full class)
  • 33. Anima3onBuilder Anima3onBuilder with the build() method creates a configured Anima&onFactory 
 Anima3onFactory with the create() method creates an Anima&onPlayer Anima3onPlayer allows to control the anima&on like FormBuilder… but for anima&ons
  • 34. Anima3onBuilder const factory = this.animBuilder.build([ ]); this.player = factory.create(this.containerRef.nativeElement); this.player.play(); this.player.onDone(() "=> resolve()); query(tilesQuery, style({ transform: 'translate3d(0, 0, 0)' }), { optional }), query( tilesQuery, stagger(50, [ animate('900ms’,style({ transform: 'rotateX(180deg)' })), ]), { optional }, ),
  • 35. query(tilesQuery, style({ transform: 'translate3d(0, 0, 0)' }), { optional }), query( tilesQuery, stagger(50, [ animate('900ms’,style({ transform: 'rotateX(180deg)' })), ]), { optional }, ), Anima3onBuilder const factory = this.animBuilder.build([ ]); this.player = factory.create(this.containerRef.nativeElement); this.player.play(); this.player.onDone(() "=> resolve());
  • 36. Anima3onBuilder const factory = this.animBuilder.build([ query(tilesQuery, style({ transform: 'translate3d(0, 0, 0)' }), { optional }), query( tilesQuery, stagger(50, [ animate('900ms’,style({ transform: 'rotateX(180deg)' })), ]), { optional }, ), ]); this.player = factory.create(this.containerRef.nativeElement); this.player.play(); this.player.onDone(() "=> resolve());
  • 38. Anima3onBuilder const factory = this.animBuilder.build([ query(tilesQuery, style({ transform: 'translate3d(0, 0, 0)' }), { optional }), query( tilesQuery, stagger(50, [ animate('900ms’,style({ transform: 'rotateX(180deg)' })), ]), { optional }, ), ]); this.player = factory.create(this.containerRef.nativeElement); this.player.play(); this.player.onDone(() "=> resolve());
  • 39. RxJS + Web Anima3ons API const animationOptions = { duration: 900, fill: ‘forwards' } const keyframes = [ { transform: 'translate3d(0, 0, 0)' }, { transform: 'rotateX(180deg)' } ]; return timer(0, 50, animationFrame) .pipe( take(tiles.length), map(i "=> tiles[i].animate(keyframes, this.animationOptions)), reduce((anims, anim) "=> [""...anims, anim], []), delay(this.animationOptions.duration), tap(anims "=> anims.forEach(anim "=> anim.cancel())), );
  • 40. teraz nie zapomnij pokazać dema :p
  • 41. More on anima&ons ‣ Angular in Mo&on: 4 approaches to anima&on ‣ Angular Router Anima&ons - what they don't tell you Ok, cheers! h`ps://twi`er.com/sulco