Vinklede animationer forklaret med eksempler

Hvorfor bruge animationer?

Moderne webkomponenter bruger ofte animationer. Cascading Style-ark (CSS) bevæbner udviklere med værktøjerne til at skabe imponerende animationer. Ejendomsovergange, entydigt navngivne animationer, nøglerammer med flere dele er mulige med CSS. De animerede muligheder er uendelige takket være CSS.

I en moderne webapplikation fokuserer animation brugerens opmærksomhed. Gode ​​animationer søger at lede brugerens opmærksomhed på en tilfredsstillende, produktiv måde. Animationer bør ikke være irriterende for brugeren.

Animationer giver feedback i form af bevægelse. De viser brugeren, at applikationen aktivt håndterer deres anmodninger. Noget så simpelt som et synligt knaptryk eller en læser, når applikationen skal indlæse, engagerer brugerens opmærksomhed.

Animationer fortsætter med at vokse mere og mere relevant i Angular's tilfælde. Google udvikler Angular, mens den promoverer materialedesignfilosofien. Det tilskynder koncise brugergrænseflader (UI) suppleret med animeret brugerfeedback. Det får webapplikationer til at føle sig noget levende og sjove at bruge.

Angular-samfundet udvikler et kerne-widgetbibliotek kaldet Material2. Dette projekt tilføjer en række widgetmoduler til Angular. De fleste af dem har animationer. For at forstå, hvordan de fungerer, anbefaler denne artikel at studere CSS-animationer, før du læser videre.

Vinklede animationer er rammens strømlinede version af, hvad CSS indbygget giver. CSS er kerneteknologien til kantede animationer, der forekommer i webbrowseren. CSS er dog uden for denne artikels rækkevidde. Det er tid til at tackle kantede animationer front-on.

Opsætning af animationer

Før animering skal den BrowserAnimationsModuleinkludere i rodmodulets importarray. Den er tilgængelig fra @angular/platform-browser/animations. Denne NgModule sikrer, at animationer fungerer for den givne platform. Denne artikel antager standardwebbrowseren for hvert eksempel.

Vinklede animationer erklærer inden for @Componentmetadataene. @Componentdekorerer en klasse for at skelne den som en komponent til Angular. Dens metadata indeholder komponentkonfigurationer inklusive animations: []feltet. Hvert array-element fra dette felt repræsenterer en animationsudløser ( AnimationTriggerMetadata).

Animationer er eksklusive for deres værtkomponent via dekoratørens metadata. Animationer kan kun bruges i værtskomponentens skabelon. Animationer arver ikke til komponentens børn. Der er en nem omgåelse for dette.

Du kan altid oprette en separat fil, der eksporterer en matrix. Enhver komponentklasse kan importere denne matrix fra toppen af ​​dens værtsfil. Det importerede array-token går derefter ind i komponentens animationsmetadata. Gentag denne proces for andre komponenter, der kræver det samme array i deres animationsmetadata.

Med indholdsprojektion kan du anvende animationer til komponent A's indhold DOM (Document Object Model). Komponent B, der indpakker dette indhold DOM kan projicere indholdet i sin egen skabelon. Når det er gjort, negerer animationerne af komponent A ikke. Komponent B inkorporerer As animationer gennem projektion af indhold.

OKAY. Du ved, hvordan du konfigurerer animationer, og hvor du skal erklære dem. Implementering er det næste trin.

Animationsmetoder

Vinklede animationer bruger en række metodeopkald, der kan importeres fra @angular/animations. Hvert element i @Componentanimationsarrayet begynder som en enkelt metode. Dens argumenter løses ud som en sekvens af opkald af højere ordensmetoder. Den følgende liste viser nogle af de metoder, der bruges til at opbygge vinklede animationer.

  • trigger(selector: string, AnimationMetadata[])

vender tilbage AnimationTriggerMetadata

  • state(data: string, AnimationStyleMetadata, options?: object)

vender tilbage AnimationStateMetadata

  • style(CSSKeyValues: object)

vender tilbage AnimationStyleMetadata

  • animate(timing: string|number, AnimationStyleMetadata|KeyframesMetadata)

vender tilbage AnimationAnimateMetadata

  • transition(stateChange: string, AnimationMetadata|AnimationMetadata[], options?: object)

vender tilbage AnimationTransitionMetadata

Mens der helt sikkert er flere metoder at vælge imellem, håndterer disse fem metoder det grundlæggende. At prøve at forstå disse kernemetoder som en liste hjælper ikke meget. Bullet-by-bullet forklaringer efterfulgt af et eksempel giver bedre mening om det.

trigger (vælger: streng, AnimationMetadata [])

Den trigger(...)fremgangsmåde indkapsler et enkelt element i animation inde i animationer array.

Metodens første argument selector: stringmatcher [@selector]medlemsattributten. Det fungerer som et attributdirektiv i komponentskabelonen. Det forbinder i det væsentlige animationselementet med skabelonen via en attributvælger.

Det andet argument er et array, der indeholder en liste over anvendelige animationsmetoder. Det trigger(...)holder det helt i et enkelt array.

tilstand (data: streng, AnimationStyleMetadata, optioner ?: objekt)

Den state(...)metode fastsættes den endelige tilstand af animationen. Det anvender en liste over CSS-egenskaber på målelementet, når en animation er afsluttet. Dette er så det animerede elements CSS matcher animationens opløsning.

Det første argument matcher værdien af ​​de data, der er bundet til animationsbinding. Det vil sige, at den værdi, der er bundet til [@selector]i skabelonen, matcher det første argument for a state(...). Datas værdi bestemmer den endelige tilstand. Ændringen af ​​værdien bestemmer animationsmidlerne (se transition(...)).

Det andet argument er vært for de CSS-stilarter, der gælder for et element efter animation. Stilarter bliver sendt ind ved at påkalde style(...)og videregive de ønskede stilarter som et objekt til sit argument.

En liste med valgmuligheder optager valgfrit det tredje argument. Standardindstillingerne state(...)skal forblive uændrede, medmindre andet begrundes.

stil (CSSKeyValues: objekt)

Du har måske bemærket AnimationStyleMetadataflere gange i den forrige liste. Den style(...)komponent returnerer netop denne type metadata. Uanset hvor CSS-stilarter gælder, skal style(...)metoden påberåbe sig. Et objekt, der indeholder CSS-stilarter, står for sit argument.

Naturligvis overføres stilarter, der kan animeres i CSS, til Angular- style(...)metoden. Indrømmet, intet umuligt for CSS bliver pludselig muligt med Angular-animationer.

animer (timing: streng | nummer, AnimationStyleMetadata | AnimationKeyframesMetadata)

Den animate(...)funktion accepterer en timing udtryk som sin første argument. Dette argument gange, skridt og / eller forsinker metodens animation. Dette argument accepterer enten et tal- eller strengudtryk. Formateringen forklares her.

Det andet argument for animate(...)er CSS-ejendommen, der berettiger animationen. Dette tager form af den style(...)metode, der vender tilbage AnimationStyleMetadata. Tænk på animate(...)som metoden, der starter animationen.

En række nøglerammer kan også gælde for det andet argument. Keyframes er en mere avanceret mulighed, som denne artikel forklarer senere. Keyframes skelner mellem forskellige dele af animationen.

animate(...)modtager muligvis ikke et andet argument. I så fald gælder metodens animationstiming kun for CSS, der afspejles i state(...)metoderne. Ejendomsændringer i triggerens state(...)metoder animeres.

overgang (changExpr: streng, AnimationMetadata | AnimationMetadata [], valgmuligheder ?: objekt)

animate(...)initierer en animation, mens den transition(...)bestemmer, hvilken animation der skal initieres.

Det første argument består af en unik form for mikrosyntaks. Det betegner en ændring i tilstand (eller ændring i data), der finder sted. De data, der er bundet til skabelonanimationsbinding ( [selector]="value"), bestemmer dette udtryk. Det kommende afsnit med titlen "Animation State" forklarer dette koncept lidt længere.

Det andet argument for transition(...)omfatter AnimationMetadata(returneret af animate(...)). Argumentet accepterer enten en matrix af AnimationMetadataeller en enkelt forekomst.

Det første arguments værdi matcher værdien af ​​de data, der er bundet i skabelonen ( [selector]="value"). Hvis der opstår et perfekt match, evalueres argumentet med succes. Det andet argument indleder derefter en animation som reaktion på den første succes.

En liste med valgmuligheder optager valgfrit det tredje argument. Standardindstillingerne transition(...)skal forblive uændrede, medmindre andet begrundes.

Animationseksempel

import { Component, OnInit } from '@angular/core'; import { trigger, state, style, animate, transition } from '@angular/animations'; @Component({ selector: 'app-example', template: ` 

Click the button to change its color!

Toggle Me! // animation binding `, animations: [ // metadata array trigger('toggleClick', [ // trigger block state('true', style({ // final CSS following animation backgroundColor: 'green' })), state('false', style({ backgroundColor: 'red' })), transition('true => false', animate('1000ms linear')), // animation timing transition('false => true', animate('1000ms linear')) ]) ] // end of trigger block }) export class ExampleComponent { isGreen: string = 'true'; toggleIsCorrect() { this.isGreen = this.isGreen === 'true' ? 'false' : 'true'; // change in data-bound value } }

Ovenstående eksempel udfører en meget enkel farveskift med hvert klik på knappen. Selvfølgelig overgår farven hurtigt i en lineær fade som pr animate('1000ms linear'). Animationen binder sig til knappen ved at matche det første argument trigger(...)til [@toggleClick]animationens binding.

Bindingen binder til værdien af isGreenfra komponentklassen. Denne værdi bestemmer den resulterende farve som angivet af de to style(...)metoder inde i trigger(...)blokken. Animationens binding er envejs, så ændringer til isGreeni komponentklassen giver besked om skabelonbindingen. Det vil sige animationsbinding [@toggleClick].

Knapelementet i skabelonen har også en clickbegivenhed bundet til sig. Hvis du klikker på knappen, isGreenskiftes værdier. Dette ændrer data om komponentklassen. Animationsbindingen opfanger dette og påkalder dets matchende trigger(...)metode. Løgnene trigger(...)ligger inden for animationsarrayet for komponentens metadata. To ting opstår ved udløserens påkaldelse.

Den første begivenhed vedrører de to state(...)metoder. Den nye værdi af isGreenmatches mod en state(...)metodes første argument. Når det matcher, gælder CSS-typografierne for style(...)den endelige tilstand for animationsbindingens værtselement. `Den endelige tilstand træder i kraft efter al animation.

Nu for anden gang. Dataændringen, der påberåbte animationsbindingen, sammenlignes på tværs af de to transition(...)metoder. En af dem matcher ændringen i data til deres første argument. Det første knap-klik fik isGreentil at gå fra 'true' til 'false' ('true => false'). Det betyder, at den første transition(...)metode aktiverer sit andet argument.

Den animate(...)funktion, der svarer til den vel vurderede transition(...)metode, starter. Denne metode indstiller varigheden af ​​den animerede farvefade sammen med fadeens pacing. Animationen udføres, og knappen falmer til rødt.

Denne proces kan ske et vilkårligt antal gange efter et klik på et knap. Den backgroundColorpå knappen vil skifte mellem grøn og rød i et lineært fade.

Animationstilstand

Den transition(...)mikro-syntaks er værd adressering i detaljer. Vinkel bestemmer animationer og deres timing ved at evaluere denne syntaks. Der eksisterer følgende tilstandsovergange. De modellerer ændringer i data bundet til en animationsbinding.

  • ‘someValue’ => ‘anotherValue’

En animationsudløser, hvor de bundne data skifter fra 'someValue' til 'anotherValue'.

  • ‘anotherValue’ => ‘someValue’

En animationsudløser, hvor de bundne data skifter fra 'anotherValue' til 'someValue'.

  • ‘someValue’ ‘anotherValue’

Data skifter fra 'someValue' til 'anotherValue' eller omvendt.

Der findes også voidog *stater. voidangiver, at komponenten enten går ind i eller forlader DOM. Dette er perfekt til ind- og udgangsanimationer.

  • ‘someValue’ => void: værtkomponent af bundne data forlader DOM
  • void => ‘someValue’: værtkomponent af bundne data går ind i DOM

* denotes a wildcard state. Wildcard states can interpret to “any state”. This includes void plus any other change to the bound data.

Keyframes

This article touched on the basics for animating Angular applications. Advanced animation techniques exist alongside these basics. Grouping together keyframes is one such technique. Its inspired from the @keyframes CSS rule. If you have worked with CSS @keyframes, you already understand how keyframes in Angular work. It becomes just a matter of syntax

The keyframes(...) method imports from @angular/animations. It passes into the second argument of animate(...) instead of the typical AnimationStyleMetadata. The keyframes(...) method accepts one argument as an array of AnimationStyleMetadata. This can also be referred to as an array of style(...) methods.

Each keyframe of the animation goes inside the keyframes(...) array. These keyframe elements are style(...) methods supporting the offset property. offset indicates a point in the animation’s duration where its accompanying style properties should apply. Its value spans from 0 (animation start) to 1 (animation end).

import { Component } from '@angular/core'; import { trigger, state, style, animate, transition, keyframes } from '@angular/animations'; @Component({ selector: 'app-example', styles: [ `.ball { position: relative; background-color: black; border-radius: 50%; top: 200px; height: 25px; width: 25px; }` ], template: ` 

Arcing Ball Animation

Arc the Ball! `, animations: [ trigger('animateArc', [ state('true', style({ left: '400px', top: '200px' })), state('false', style({ left: '0', top: '200px' })), transition('false => true', animate('1000ms linear', keyframes([ style({ left: '0', top: '200px', offset: 0 }), style({ left: '200px', top: '100px', offset: 0.50 }), style({ left: '400px', top: '200px', offset: 1 }) ]))), transition('true => false', animate('1000ms linear', keyframes([ style({ left: '400px', top: '200px', offset: 0 }), style({ left: '200px', top: '100px', offset: 0.50 }), style({ left: '0', top: '200px', offset: 1 }) ]))) ]) ] }) export class ExampleComponent { arc: string = 'false'; toggleBounce(){ this.arc = this.arc === 'false' ? 'true' : 'false'; } }

The main difference of the above example compared to the other example is the second argument of animate(...). It now contains a keyframes(...) method hosting an array of animation keyframes. While the animation itself is also different, the technique to animate is similar.

Clicking the button causes the button to arc across the screen. The arc moves as per the keyframes(...) method’s array elements (keyframes). At the animation’s mid-point (offset: 0.50), the ball changes trajectory. It descends to its original height as it continues across the screen. Clicking the button again reverses the animation.

left and top are animatable properties after setting position: relative; for the element. The transform property can perform similar movement-based animations. transform is an expansive yet fully animatable property.

Any number of keyframes can existing between offset 0 and 1. Intricate animation sequences take the form of keyframes. They are one of many advanced techniques in Angular animations.

Animations With Host Binding

You will undoubtedly come across the situation where you want to attach an animation to the HTML element of a component itself, instead of an element in the component’s template. This requires a little more effort since you can’t just go into the template HTML and attach the animation there. Instead, you’ll have to import HostBinding and utilize that.

The minimal code for this scenario is shown below. I’ll re-use the same animation condition for the code above for consistency and I don’t show any of the actual animation code since you can easily find that above.

import { Component, HostBinding } from '@angular/core'; @Component({ ... }) export class ExampleComponent { @HostBinding('@animateArc') get arcAnimation() { return this.arc; } }

The idea behind animating the host component is pretty much the same as animating a element from the template with the only difference being your lack of access to the element you are animating. You still have to pass the name of the animation (@animateArc) when declaring the HostBinding and you still have to return the current state of the animation (this.arc). The name of the function doesn’t actual matter, so arcAnimation could have been changed to anything, as long as it doesn’t clash with existing property names on the component, and it would work perfectly fine.

Conclusion

Dette dækker det grundlæggende ved animering med Angular. Angular gør opsætning af animationer meget let ved hjælp af Angular CLI. Kom godt i gang med din første animation kræver kun en enkelt komponentklasse. Husk, animationer rammer komponentens skabelon. Eksporter dit overgangsarray fra en separat fil, hvis du planlægger at bruge det på tværs af flere komponenter.

Hvert animationsværktøj / -metode eksporteres fra @angular/animations. De arbejder alle sammen for at give et robust animationssystem inspireret af CSS. Der er flere metoder ud over, hvad denne artikel kan dække.

Nu hvor du kender det grundlæggende, er du velkommen til at udforske nedenstående links for mere om Angular-animationer.

Mere info om Angular Animations:

  • Vinklet dokumentation
  • Sådan bruges animation med Angular 6