Att animera slag av en SVG är perfekt för att simulera handskrift. Under två tutorials kommer vi att använda CSS-animering för att få en signatur att vara skön, som om du själv signerar sidan.
Här är vad vi ska bygga:
Innan vi dyker in i någon kod behöver vi en SVG-version av din signatur. Det spelar ingen roll vilken mjukvara du använder för att göra detta, men försök att hålla linjerna och kurvorna så smidiga som möjligt för bästa effekten.
Här är min, som du kan se är ritad med tre separata vägar:
Första vägenAndra vägenTredje vägenSe till att din tavla är beskuren tätt mot signaturen, spara sedan filen som en SVG.
Öppna filen i en kodredigerare kommer att avslöja SVGs XML-struktur. Beroende på vilken applikation du använde för att designa den, plus hur du sparade eller exporterade den, har du en element med några mumbo jumbo före den. Mumbo jumbo kan tas bort.
I det här fallet ser elementen som vi är kvar med något ut:
Inom vår huvudsakliga vi har en
, då en
, sedan en annan
. Det här är de tre vektorerna vi ritade, differentierade bara för att tekniskt sett har en linje ingen krökning, så den definieras annorlunda än en väg i SVG.
Vi behöver separera dessa vektorer separat med CSS lite senare, så se till att de vart och ett har ett lämpligt klassnamn. De elementet kommer sannolikt redan att ha ett ID som återspeglar skiktnamnet i den ansökan det designades med.
Jag har givit mina vektorer klassnamn beroende på vad de är (den första är "jag" i mitt namn, till exempel).
Med rättvisa kommer din SVG inte att se ganska snyggt ut. Vart och ett av dessa vektorer kommer att ha en last av koordinater, plus flera attribut begravda inom dem. Koordinaterna måste stanna, men vi kan ta bort några av de vanligt använda attributen och placera dem i vår CSS istället, hålla sakerna trevliga och torka.
Jag ska bygga detta med CodePen, men du kan använda fristående HTML- och CSS-dokument om du föredrar det. Klistra in SVG-koden direkt i ditt HTML-dokument. Ta sedan bort attributen som varje sökväg och linjelement har gemensamt, placera dem istället i CSS-dokumentet. Till exempel märker du attribut som:
fylla = "none"
stroke = "# 0F436D"
stroke-width = "2"
stroke-linecap = "rund"
stroke-linejoin = "rund"
stroke-miterLimit = "10"
Dessa kan tas bort och appliceras via CSS istället, så här:
sökväg, linje fill: none; stroke: # 2a3745; slagbredd: 2; stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 10;
Mycket renare!
För att animera slagen i denna SVG ska vi använda en teknik som först diskuterades av Jake Archibald. Tanken är följande: vart och ett av dessa vektorer kommer att ges a streckad stroke. Vi gör detta genom att tillämpa en stroke-dasharray
värde inom CSS:
För vart och ett av dessa vektorer gör vi stroke-dasharray
exakt längden på banan, så var och en har en enda streck som täcker hela längden. Det här tar lite försök och fel, men i vårt fall ser värdena ut så här:
.stroke-I stroke-dasharray: 80; .slags-en stroke-dasharray: 360; .Skaka-blomstra stroke-dasharray: 40;
Nu, för att kunna animera dessa slag, måste vi kompensera varje streck så att gap täcker vektorn, inte den rusa. Går det förnuftigt? Dessa illustrationer kan hjälpa till. I den här första, föreställ dig att den streckade linjen används för att täcka blomningen i slutet av signaturen.
Nu i den här har vi kompenserat bindestrecket, så det är gapet som är över blomstrandet:
Nu behöver vi bara använda CSS för att animera från offset-staten till den andra.
CSS-animering är beroende av att först definiera nyckelbilder. Varje keyframe representerar stater längs en tidslinje, så gör våra webbläsare animationerna mellan dem.
Låt oss först se hur denna dash offset kan animeras. Vi använder första stroke, "I", och animerar mellan två stater. Börja med att skapa några nyckelbilder:
@keyframes write1 0% stroke-dashoffset: 80; 100% stroke-dashoffset: 0;
Här ger vi keyframes ett namn (write1
) och använda stenografi syntax specificera att i början av tidslinjen (0%
) vi vill ha stroke-dashoffset
att vara 80
. Med andra ord: bindestrecket, som exakt är 80 px långt, kommer att kompenseras helt.
I slutet av tidslinjen (vid 100%
) vi vill ha stroke-dashoffset
att vara 0
, så bindestrecket återigen täcker vektorn.
Nu har vi våra nyckelramar, låt oss bifoga dem till en animering. Vi lägger till en annan deklaration till vår stroke-I
regel:
.stroke-I stroke-dasharray: 80; animering: write1 3s oändlig linjär;
Här använder du animering
egendom säger vi att vi vill använda write1
nyckelbilder definierade för en stund sedan, vi vill att hela saken ska vara exakt 3
sekunder, vi vill att animationen ska slinga oändligt och vi vill att hastigheten ska vara linjär
(så att det inte finns någon acceleration eller retardation).
Här är vad vi får:
Notera: Jag använder Autoprefixer i CodePen vilket sparar mig att behöva använda webbläsarprefix på animeringsmaterialen.
Vi måste definiera ytterligare två uppsättningar nyckelbilder (skriv2
och write3
) för de återstående vektorerna i signaturen - och vi måste kompensera av de rätta strecklängderna vi upptäckte tidigare:
@keyframes write2 0% stroke-dashoffset: 360; 100% stroke-dashoffset: 0; @keyframes write3 0% stroke-dashoffset: 40; 100% stroke-dashoffset: 0;
Då måste vi tillämpa dessa animationer på de återstående två vektorerna:
.stroke-en stroke-dasharray: 360; animering: write2 3s oändlig linjär; .Skaka-blomstra stroke-dasharray: 40; animering: write3 3s oändlig linjär;
Här är vad vi får:
Nu kommer vi någonstans! Varje vektor animerar perfekt, i en linjär rörelse som varar i 3 sekunder.
Nästa steg? För att få dem att animera i turordning.
För närvarande har vi tre slag alla animerade samtidigt. Men vi vill helst att "jag" ska animera, då "an", då äntligen blomstra i slutet. Om vi skulle visualisera det längs en tidslinje kan det se ut så här:
Vi kan faktiskt representera dessa delar av tidslinjen perfekt i våra CSS-nyckelbilder. Till exempel är det första avsnittet (från 0% till 33,3%) när vi vill att vår "jag" ska animera, så vi ändrar nyckelbilderna till 33,3% i stället för 100%:
@keyframes write1 0% stroke-dashoffset: 80; 33,3% stroke-dashoffset: 0;
Med tanke på att alla tre animationerna är lika långa (3 sekunder) kan vi se till att den andra inte börjar till 33,3%, när den första animationen är klar:
@keyframes write2 0%, 33.3% stroke-dashoffset: 360; 100% stroke-dashoffset: 0;
Här är vad som ger oss:
De första två animationerna flyter snyggt, så låt oss förbättra sakerna genom att få den andra att sluta med 66,6%, varpå den sista animationen kan börja. Våra nyckelbilder kommer att se ut så här:
@keyframes write1 0% stroke-dashoffset: 80; 33,3% stroke-dashoffset: 0; @keyframes write2 0%, 33.3% stroke-dashoffset: 360; 66,6% stroke-dashoffset: 0; @keyframes write3 0%, 66.6% stroke-dashoffset: 40; 100% stroke-dashoffset: 0;
Och sekvensen ser så här ut:
Det vi har är bra, men det är inte perfekt - verkligen långt från en realistisk penna-rörelse. Var och en av dessa tre vektorer ritas under en sekund, oberoende av dess längd. Mellanvektorn är längre än den sista, så det borde logiskt ta längre tid att rita. En bättre tidslinje kan se ut så här:
För extra realism finns det även ett gap mellan den första vektoravslutningen och den andra början. Så låt oss ändra våra nyckelramsvärden för att återspegla det:
@keyframes write1 0% stroke-dashoffset: 80; 20% stroke-dashoffset: 0; @keyframes write2 0%, 25% stroke-dashoffset: 360; 90% stroke-dashoffset: 0; @keyframes write3 0%, 90% stroke-dashoffset: 40; 100% stroke-dashoffset: 0;
Slutligen, låt oss snabba på saker genom att ändra alla 3s
värden till 2s
. Vi kan också uppdatera animeringsdeklarationerna så att var och en bara kör en gång, inte oändligt looping:
animering: write1 2s 1 linear;
Du kanske vill spela med linjär
värde, istället lägga till lite lättnad, till exempel lindra-in
, enkel in-out
, lindra-out
etc. för att göra rörelsen mindre likformig. Vad ger det alla oss?
Vi har gjort stora framsteg och lärt oss mycket på vägen! I nästa handledning tar vi saker ytterligare ett steg med Waypoints.js för att hjälpa oss att styra när animationen äger rum. vi ses där!