Tillsats Animation med Webb Animationer API

0
104

Dessa funktioner har inte landat i någon stabil webbläsare i skrivande stund. Men allt diskuteras är redan i Firefox Nightly som standard och viktiga delar i Chrome Canary (med Experimentell Plattform för Webben Har flaggan aktiverad), så jag rekommenderar att använda en av dessa webbläsare (när man läser denna artikel) att se så många av de funktioner i åtgärder som möjligt.

Oavsett din bästa metoden för att animation på nätet, det kommer att finnas tillfällen som du behöver för att animera samma fastighet i separata animationer. Du kanske har en hover-effekt som anpassar en bild och en click-händelse som aktiverar en translate — både påverkar förändra. Som standard kan dessa animationer inte vet något om den andra, och endast ett visuellt kommer att tillämpas (eftersom de påverkar samma CSS-egenskapen och det andra värdet kommer att ändras).

elementet.animera({
förändra: [‘translateY(0)’, ‘translateY(10px)’]
}, 1000);

/* Detta kommer att helt åsidosätta den föregående animering */
elementet.animera({
förändra: [‘scale(1)’, ‘skala(1.15)’]
}, 1500);

Den andra animationen i denna Webb-Animationer API exempel är den enda som skulle vara visuellt återges i detta exempel som både animationer spela på samma gång och det var den sista definitionen.

Ibland har vi till och med större idéer där vi vill ha en grundläggande animation och sedan baserat på någon interaktion med användaren förändring i tillstånd som vi smidigt ändra animationen lite halvvägs utan att påverka dess befintliga varaktighet, keyframes, eller lättnader. CSS-Animationer och den aktuella webbsidan Animationer API i stabil webbläsare i dag inte kan göra detta ur lådan.

Ett Nytt Alternativ

Webben Animationer specifikation introducerar komposit fastighet och tillhörande iterationComposite). Standard komposit är ‘ersätt’ och har ett beteende som vi har haft i flera år nu om ett aktivt animera fastighetens värde helt enkelt ersätter alla tidigare inställt värde, antingen från en regel eller en annan animation.

‘Lägg till’ värdet är där saker och ting förändras från tidigare normer.

elementet.animera({
förändra: [‘scale(1)’, ‘skala(1.5)’]
}, {
längd: 1000,
fyllning: ‘båda’
});
elementet.animera({
förändra: [‘rotate(0deg)’, ‘rotate(180deg)’]
}, {
längd: 1500,
fyllning: ‘båda’,
komposit: ‘lägg till’
});

Nu är både animationer kommer att ses som webbläsaren på att flyga räknar ut lämplig omvandling vid en given punkt i elementets tidslinje redovisning för både förändringar. I vårt exempel, lättnader ‘linjär’ som standard och animationer starta på samma tid, så att vi kan bryta ut vad den effektiva förändra är vid varje given tidpunkt. Till exempel:

  • 0ms: skala(1) rotera(0deg)
  • 500ms: skala(1.25) rotera(60deg) (halvvägs genom första animering, 1/3 genom andra)
  • 1000ms: skala(1.5) rotera(120deg) (i slutet av första, 2/3 genom andra)
  • 1500ms: skala(1.5) rotera(180deg) (i slutet av andra)

Se Pennan Animation Sammansatt av Dan Wilson (@danwilson) på CodePen.

Så Låt oss Få Kreativa

En individ animation inte bara består av en start staten och slutet staten — det kan ha sin egen lättnader, iteration räkna, varaktighet, och mer keyframes i mitten. Medan en del är mitten av animation kan du kasta ett extra omvandling på det med sin egen timing alternativ.

Se Pennan Lägga till fler omvandla animationer av Dan Wilson (@danwilson) på CodePen.

Detta exempel kan du lägga till flera animationer på samma element, alla påverkar omvandla fastigheten. För att hålla från att gå ut i detta exempel kommer vi begränsa var och animation till en enstaka omvandling funktion vid en tidpunkt (till exempel bara en skala), börjar på ett default-värde (till exempel skala(1) eller translateX(0)), och slutar på en rimlig slumpmässigt värde på samma omvandling funktion, som upprepas i det oändliga. Nästa animation kommer att påverka en annan enskild funktion med sin egen randomiserade varaktighet och lättnader.

elementet.animera(getTransform(), //t ex { transform: [‘rotate(0deg),” rotera(45deg)’] }
{
varaktighet: getDuration(), //mellan 1000 och 6000ms
iterationer: Infinity,
komposit: ‘lägg till’,
lättnader: getEasing() //ett av två alternativ
});

När varje animation startar, kommer webbläsaren att effektivt hitta där det är i sin tidigare tillämpade animationer och starta en ny rotation animation med den angivna tidpunkten alternativ. Även om det redan finns en rotation går i motsatt riktning, kommer webbläsaren att göra matematik för att räkna ut hur mycket en rotation som behöver hända.
Eftersom varje animation har sin egen timing alternativ, är du sannolikt inte att se exakt samma rörelse upprepas i detta exempel när du har lagt till ett par. Detta ger animering för en fräsch känsla som du titta på det.

Eftersom varje animation i vårt exempel börjar vid den förvalda värde (0 till översättningar och 1 för skalning) vi får en mjuk start. Om vi istället hade keyframes som { transform: [‘skala(.5)’, ‘skala(.8)’] } vi skulle få hoppa eftersom de inte har denna skala innan och helt plötsligt börjar sin animering vid halv skala.

Hur är värden som läggs?

Omvandling värden följer syntaxen i i spec, och om du lägger till en förändring du lägga till en lista.

För att omvandla animationer A, B och C den resulterande beräknas omvandla värdet kommer att vara [nuvarande värde i] [aktuella värdet i B] [aktuella värdet i C]. Till exempel, anta följande tre animationer:

elementet.animera({
förändra: [‘translateX(0)’, ‘translateX(10px)’]
}, 1000);

elementet.animera({
förändra: [‘translateY(0)’, ‘translateY(-20px)’]
}, {
längd:1000,
komposit: ‘lägg till’
});

elementet.animera({
förändra: [‘translateX(0)’, ‘translateX(300px)’]
}, {
längd:1000,
komposit: ‘lägg till’
});

Varje animation körs under 1 sekund med en linjär lättnader, så halvvägs genom animationer den resulterande omvandla skulle ha värdet translateX(5px) translateY(-10px) translateX(150px). Easings, varaktigheter, förseningar, och mer kommer att påverka värdet som du går längs.

Transformer är inte det enda vi kan animera, dock. Filter (hue-rotera(), blur(), etc) följer ett liknande mönster där de poster som läggs till i ett filter i listan.

Vissa egenskaper för att använda ett nummer som ett värde, till exempel opacitet. Här siffrorna kommer att lägga upp till ett enda belopp.

elementet.animera({
opacitet: [0, .1]
}, 1000);

elementet.animera({
opacitet: [0, .2]
}, {
längd:1000,
komposit: ‘lägg till’
});

elementet.animera({
opacitet: [0, .4]
}, {
längd:1000,
komposit: ‘lägg till’
});

Eftersom varje animation igen 1s varaktighet med en linjär lättnader, kan vi beräkna det resulterande värdet på en punkt i denna animation.

  • 0ms: opacitet: 0 (0 + 0 + 0)
  • 500ms: opacitet: .35 (.05 + .1 + .2)
  • 1000ms: opacitet: .7 (.1 + .2 + .4)

Som sådan, du kommer inte att se mycket, om du har flera animeringar som har värdet 1 som en keyframe. Det är ett max-värde för sin visuella staten, så att lägga till upp till värden bortom det kommer att se ut på samma sätt som om det var för bara 1.

Se Pennan Lägga till fler opacitet animationer av Dan Wilson (@danwilson) på CodePen.

Liknande opacitet och andra egenskaper som accepterar antal värderingar, egenskaper som accepterar längder, procenttal eller färger kommer också att summan till ett enda resultat värde. Med färger, du måste komma ihåg att de också har ett max värde (oavsett om de är max 255 i rgb() eller 100% för mättnad/lätthet i hsl()), så att dina resultat kan max ut till en vit. Med längder, kan du växla mellan enheter (t.ex px för att vmin) som om det är inne i en calc().

För mer information, specifikationer beskrivs de olika typer av animation och hur resultatet beräknas.

Att arbeta med att Fylla Lägen

När du inte gör en oändlig animation (om du använder en sammansatt eller inte) som standard animation kommer inte att hålla slutet staten som animationen slutar. Fyll egendom som tillåter oss att ändra det beteendet. Om du vill ha en smidig övergång när du lägger till en begränsad animation, du sannolikt kommer att ha en fill-mode av antingen framåt eller både att se till att slutet staten fortfarande.

Se Pennan Spiral: Komposit Till + Fyller Framåt av Dan Wilson (@danwilson) på CodePen.

Detta exempel har en animation med en spiral väg genom att ange en rotation och en översättning. Det finns två knappar för att lägga till en ny andra animationer med en extra liten översättning. Eftersom de anger fyllning: ‘framåt’ varje ytterligare översättning effektivt förblir en del av förvandla listan. Den växande (eller krymper) spiral anpassar sig smidigt med varje omräkningsjustering eftersom det är en tillsats animation från translateX(0) till ett nytt belopp och fortsätter på den nya belopp.

Ackumulera animationer

Den nya sammansatta alternativ har ett tredje värde — ‘samla’. Det är begreppsmässigt i överensstämmelse med “lägg till” utom vissa typer av animationer, kommer att bete sig annorlunda. Håller med vårt förändra, låt oss börja med ett nytt exempel med hjälp av “lägg till” och sedan diskutera hur “samla” är olika.

elementet.animera({
förändra: [‘translateX(0)’, ‘translateX(20px)’]
}, {
längd: 1000,
komposit: ‘lägg till’
});
elementet.animera({
förändra: [‘translateX(0)’, ‘translateX(30px)’]
}, {
längd: 1000,
komposit: ‘lägg till’
});
elementet.animera({
förändra: [‘scale(1)’, ‘skala(.5)’]
}, {
längd: 1000,
komposit: ‘lägg till’
});

På 1 sekund mark (slutet av animeringar), den verkliga värdet kommer att vara:

förändra: translateX(20px) translateX(30px) skala(.5)

Som visuellt kommer att driva ett element till höger 50px och sedan skala ner det till hälften bredd och halv höjd.

Om varje animation hade varit att använda ‘samla’ istället, då skulle resultatet bli:

förändra: translateX(50px) skala(.5)

Som visuellt kommer att driva ett element till höger 50px och sedan skala ner det till hälften bredd och halv höjd.

Inget behov för en dubbel ta, det visuella resultatet är i själva verket exakt samma — så hur är ‘samla’ annorlunda?

Tekniskt när ackumulera en omvandla animation vi är inte längre alltid lägga till en lista. Om en omvandling funktion redan finns (såsom translateX() i vårt exempel) vi kommer inte att lägga till ett värde när vi börjar vår andra animation. Istället, den inre värden (dvs längden värden) kommer att införas och placeras i befintlig funktion.

Om vår visuella resultaten är de samma, varför alternativet att samla inre värden finns?

I händelse av att förändra, för att på listan över funktioner frågor. Omvandlingen translateX(20px) translateX(30px) skala(.5) är annorlunda än translateX(20px) skala(.5) translateX(30px) eftersom varje funktion påverkar koordinatsystem av de funktioner som följer med det. När du gör en skala(.5) i mitten, den senare funktioner kommer också att ske vid halv skala. Därför med detta exempel translateX(30px) visuellt kommer att göra som ett 15px översättning till höger.

Se Pennan Visuell Referens: Omvandla koordinatsystem av Dan Wilson (@danwilson) på CodePen.

Därför, med ackumulering vi kan ha en ordning som är annorlunda då när vi alltid att lägga till värdena i listan.

Ackumulera för Varje Iteration

Jag nämnde innan att det är också en ny relaterade iterationComposite egendom. Det ger möjlighet att göra en del av de beteenden vi har redan diskuterat utom på en enda animation från en iteration till nästa.

Till skillnad från komposit, hotellet har två gällande värden: ‘ersätt’ (standard beteende som du redan känner till och älskar) och ‘samla’. Med ‘samla’ värden följer redan diskuterat ackumulationsprocessen för listor (som med transform) eller läggs samman för antalet fastigheter som opacitet.

Som ett första exempel, det visuella resultatet för de följande två animationer skulle vara identiska:

intervaller.animera([{
förändra: “rotera(0deg) translateX(0vmin)`,
opacitet: 0
}, {
förändra: “rotera(50deg) translateX(2vmin)`,
opacitet: .5
}], {
längd: 2000,
iterationer: 2,
fyllning: ‘framåt’,
iterationComposite: ‘samla’
});

intervals2.animera([{
förändra: “rotera(0deg) translateX(0vmin)`,
opacitet: 0
},{
förändra: “rotera(100deg) translateX(4vmin)`,
opacitet: 1
}], {
längd: 4000,
iterationer: 1,
fyllning: ‘framåt’,
iterationComposite: ‘ersätt’ //default-värde
});

Den första animeringen är bara stöta upp sin opacitet av .5, roterande 50 grader, och flytta 2vmin för 2000 millisekunder. Det har våra nya iterationComposite värde och är inställd på att köra för 2 iterationer. Därför, när animationen slutar, det kommer att få köra för 2 * 2000 ms och nådde en opacitet 1 (2 * .5), roteras och 100 grader (2 * 50deg) och översatt 4vmin (2 * 2vmin).

Se Pennan Spiral med WAAPI iterationComposite av Dan Wilson (@danwilson) på CodePen.

Bra! Vi använde bara en ny fastighet som stöds bara i Firefox Nightly att återskapa det som vi redan kan göra med Webben Animationer API (eller CSS)!
De mer intressanta aspekterna av iterationComposite spelar in när du kombinerar den med andra objekt på Webben Animationer spec som kommer snart (och också redan i Firefox Nightly).

Inställning Nya Effektalternativ

Webben Animationer API som det står i en stabil webbläsare idag är i stort sett i nivå med CSS-Animationer med några extra finesser som en playbackRate möjlighet och förmåga att hoppa/söka på olika punkter. Dock Animation objekt är att få möjlighet att uppdatera effekt och timing alternativ på redan kör animationer.

Se Pennan WAAPI iterationComposite & sammansatt av Dan Wilson (@danwilson) på CodePen.

Här har vi ett inslag med två animationer som påverkar omvandla fastigheten och att förlita sig på komposit: ‘lägg till’ — en som gör elementet rör sig över skärmen horisontellt och flyttar den vertikalt på ett successivt sätt. Slutet staten är lite högre på skärmen än i början staten i denna andra animation, och med iterationComposite: ‘samla’ det blir högre och högre. Efter åtta iterationer animeringen är klar och vänder sig till en annan åtta iterationer tillbaka ner till botten av skärmen där processen börjar om igen.

Vi kan ändra hur långt upp i tv-animation går genom att ändra antalet iterationer i farten. Dessa animationer är att spela på obestämd tid, men du kan ändra den nedrullningsbara till en annan iteration räkna i mitten av animation. Om du, till exempel, kommer från sju iterationer till nio och du ser den sjätte iteration för närvarande, din animation fortsätter att köra som om ingenting har förändrats. Men, du kommer att se att istället för att starta en omvänd efter att nästa (den sjunde) iteration, det kommer att fortsätta för två. Du kan även byta i ny nyckelruta, och animeringen timing kommer att förbli oförändrad.

animation.effekt.timing.iterationer = 4;
animation.effekt.setKeyframes([
{ transform: ‘- skala(1)’ },
{ transform: ‘- skala(1.2)’ }
]);

Ändra animationer midway får inte vara något som du kommer att använda varje dag, men eftersom det är något nytt på webbläsare-nivå kommer vi att lära av sina möjligheter som funktionalitet blir mer allmänt tillgänglig. Ändra iteration räknas kunde vara bra för ett spel när en användare få en bonus runda och spelet fortsätter längre än vad som ursprungligen var avsett. Olika keyframes kan få betydelse när en användare går från vissa fel tillstånd till en framgång staten.

Vart går vi härifrån?

Den nya sammansatta alternativ och möjligheten att ändra tidpunkten alternativ och keyframes öppna nya dörrar för reaktiv och koreograferad animationer. Det finns också en pågående diskussion i CSS-arbetsgruppen om att lägga till denna funktionalitet i CSS, även utanför ramen av animeringar — påverkar kaskad på ett nytt sätt. Har vi tid innan något av detta kommer att landa i en stabil större webbläsare, men det är spännande att se nya alternativ kommer och ännu mer spännande att kunna experimentera med dem i dag.