Staten Ändra Gradienter med CSS Övergångar och Animeringar

0
16

Tillbaka under 2012 och Internet Explorer 10 kom ut och, bland annat, att det slutligen stöds CSS gradienter och, utöver det, förmågan att animera dem med bara CSS! Några andra webbläsare som stöds detta på den tiden, men jag var hoppfull inför framtiden.

Tyvärr, sex år har gått och ingenting har förändrats i denna avdelning. Edge stödjer animera gradienter med CSS, precis som IE 10 gjorde då, men ingen annan webbläsare har stöd för detta. Och medan animera bakgrund-storlek eller background-position eller opacitet eller rotation av en pseudo-element i lager på toppen kan ta oss en lång väg när det gäller att uppnå coola effekter, dessa lösningar är fortfarande begränsad.

Det är effekter vi kan inte föröka sig utan att lägga till massor av extra element eller massor av extra gradienter, såsom “mörkar” – effekten ses nedan.

Mörkarna effekt (demo, Edge/ IE 10+).

I Kanten, får ovanstående effekt uppnås med en keyframe animation:

html {
bakgrund: linear-gradient(90deg, #f90 0%, #444 0) 50%/ 5em;
animation: persienner 1s ease-in-out oändliga alternativ;
}

@keyframes persienner {
till {
background-image: linear-gradient(90deg, #f90 100%, #444 0);
}
}

Om det verkar VÅT, vi kan TORKA upp det med en touch av Sass:

@funktion blinds($öppet: 0) {
@return linear-gradient(90deg, #f90 $öppna*100%, #444 0);
}

html {
bakgrund: blinds() 50%/ 5em;
animation: persienner 1s ease-in-out oändliga alternativ;
}

@keyframes persienner {{ background-image: blinds(1) } }

Medan vi har gjort den kod vi skriver och vad vi behöver för att redigera senare mycket lättare att underhålla, vi har fortfarande upprepning i den sammanställda CSS och vi är begränsade av det faktum att vi endast kan animera mellan hållplatser med samma enhet — medan informationsinsatser från 0% till 100% fungerar alldeles utmärkt att använda den 0 eller 0px istället för 0% resultaten i no animation längre. För att inte nämna att Chrome och Firefox bara vända från orange till grå med ingen stopp-position animation på alla!

Lyckligtvis dessa dagar har vi ett ännu bättre alternativ: CSS variabler!

Direkt ur lådan, CSS variabler är inte animatable, men vi kan få en övergång (men inte animeringar!) effekter om den egendom som vi använder dem för är animatable. Till exempel, när den används inne i en omvandla funktion, vi kan övergå till att förvandla fastigheten.

Låt oss betrakta exemplet på en box som får flyttas och mosade när en kryssruta är markerad. På denna ruta, vi satt en transform som beror på en faktor –f som är inledningsvis 1:

.box {
/* grundläggande stilar som dimensioner och bakgrund */
–f: 1;
förändra: översätta(calc((1 – var(–f))*100vw)) scalex(var(–f));
}

När kryssrutan är :kollade, vi ändra värdet av CSS variabel –f .5:

:kollade ~ .box { –f: .5 }

Att sätta en övergång på .box gör att det går smidigt från den ena staten till den andra:

.box {
/* samma stil som innan */
övergång: transform .3s lätthet.
}

Observera att detta inte riktigt fungerar i den nuvarande versionen av Kanten på grund av detta fel.

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Men, CSS gradienter är bakgrunden bilder, som är bara animatable i Kanten och IE 10+. Så även om vi kan göra saker och ting lättare för oss själva och minska mängden genererat CSS för övergångar (se kod nedan), vi är fortfarande inte gör framsteg i form av ett utökat stöd.

.mörkarna {
bakgrund: linear-gradient(90deg, #f90 var(–pos, 0%), #444 0) 50%/ 5em;
övergång: .3s ease-in-out;

:kollade ~ & { –pos: 100%; }
}

Öppen/stäng persienner på att markera/avmarkera kryssrutan (demo, Kant).

Ange Houdini, som tillåter oss att registrera egna egenskaper och sedan animera dem. Detta är för närvarande stöds endast av Blink webbläsare bakom Experimentell Plattform för Webben har flaggan, men det är fortfarande ett utökat stöd en bit från Kanten ensam.

Experimentell Plattform för Webben funktioner flagga som aktiveras i Chrome.

Gå tillbaka till vårt exempel, vi registrerar –pos egna fastigheten:

CSS.registerProperty({
namn: ‘–pos’,
syntax: ‘< – längd-andel>’,
initialValue: ‘0%’
});

Observera att <length % > betyder att det accepterar inte bara längd och andel värden, men också calc() kombinationer av dem. Däremot, <längd> | <procentsats> accepterar endast längd och andel värden, men inte calc() kombinationer av dem.

Men att göra detta inte göra någon skillnad i Chrome, även med flaggan aktiverad, förmodligen för att, i fråga om övergångar, vad som gått över är den egendom vars värde beror på CSS rörliga och kan inte CSS rörlig själv. Och eftersom vi i allmänhet inte kan övergången mellan två bakgrundsbilder i Chrome i allmänhet, detta misslyckas också.

Det fungerar i Kanten, men det fungerade i Kanten även utan att registrera –pos variabel eftersom Edge gör det möjligt för oss att övergången mellan gradienter i allmänhet.

Vad som fungerar i Blink webbläsare med flaggan aktiverad är att ha en animering i stället för en övergång.

html {
bakgrund: linear-gradient(90deg, #f90 var(–pos, 0%), #444 0) 50%/ 5em;
animation: persienner .85s ease-in-out oändliga alternativ;
}

@keyframes persienner {{ –pos: 100%; } }

Detta är dock numera inte arbetar i Kanten längre, för även om Kant kan animera mellan gradient som bakgrund, det kan inte jag göra samma sak för anpassade egenskaper.

Så vi måste ta en alternativ metod för Kanten här. Det är där @stöd kommer väl till pass, eftersom alla vi har att göra är att kontrollera om a-ms – prefixet fastighet stöds.

@funktion grad($pos: 100%) {
@return linear-gradient(90deg, #f90 $pos, #444 0);
}

html{
/* samma som innan */

@stöder (-ms-user-select: ingen) {
background-image: grad(0 procent).
animation-namn: persienner-alt -;
}
}

@keyframes persienner-alt – {{ background-image: grad() } }

Stoppa positioner är inte det enda vi kan animera detta sätt. Vi kan göra samma sak för lutning vinkel. Tanken bakom det är ganska mycket samma, förutom att nu är det vår animation är inte ett omväxlande ett längre och vi använder en easeInOutBack typ av tidtagningen.

@funktion grad($ang: 1turn) {
@return linear-gradient($ang, #f90 50%, #444 0);
}

html {
bakgrund: grad(var(–ang, 0deg));
animation: rot 2s kubik-bezier(.68, -.57, .26, 1.65) oändlig;

@stöder (-ms-user-select: ingen) {
background-image: grad(0turn);
animation-namn: rot-alt -;
}
}

@keyframes rot {{ –ang: 1turn; } }

@keyframes rot-alt – {{ background-image: grad(); } }

Kom ihåg att, precis som i fallet med stopp-positioner, kan vi bara animera mellan gradient vinklar uttryckta i samma enhet i Kanten, så ringer vår Sass funktion med grad(0deg) istället för grad(0turn) inte fungerar.

Och, naturligtvis, CSS-variabel använder vi nu accepterar vinkel värden i stället för längder och procentsatser:

CSS.registerProperty({
namn: ‘–ang’,
syntax: ‘<vinkeln>’,
initialValue: ‘0deg’
});

Sveper runt (live demo, Blink webbläsare med flagga och Kant).

På ett liknande sätt, vi kan också animera radiell gradienter. Och det riktigt coola med CSS variabel inställning är att det tillåter oss att animera olika delar av lutningen på olika sätt, vilket är något som inte är möjligt när animering gradienter hela vägen Kanten gör (vilket är anledningen till att följande demos fungerar inte så bra i Kanten).

Låt säga att vi har följande radial gradient():

$p: 9 procent.

html {
–x: #{$p};
–y: #{$p};
bakgrund: radial gradient(cirkeln var (- x) var(–y), #f90, #444 $s);
}

Vi registrerar –x –y variabler:

CSS.registerProperty({
namn: ‘- x’,
syntax: ‘< – längd-andel>’,
initialValue: ‘0%’
});

CSS.registerProperty({
namn: –y’,
syntax: ‘< – längd-andel>’,
initialValue: ‘0%’
});

Då kan vi lägga till animationer:

html {
/* samma som innan */
animation: en 0s ease-in-out -2.3 s alternativa oändlig;
animation-namn: x, y;
animation-längd: 4.1 s, 2.9 s.
}

@keyframes x {{ –x: #{100% – $p} } }
@keyframes y {{ –y: #{100% – $p} } }

Resultatet som vi får kan ses nedan:

Rörligt ljus (live demo, Blink webbläsare med flagga).

Vi kan använda den här tekniken för att animera de olika anpassade egenskaper vi inne i lutning funktion för att göra persienner i vårt första exempel nära den andra vägen istället för att gå tillbaka. För att göra detta, vi införa två CSS-variabler, –c0 och –c1:

$c: #f90 #444;

html {
–c0: #{n: te($c, 1)};
–c1: #{n: te($c, 2)};
bakgrund: linear-gradient(90deg, var(–c0) var(–pos, 0%), var(–c1) 0) 50%/ 5em;
}

Vi registrerar alla dessa anpassade egenskaper:

CSS.registerProperty({
namn: ‘–pos’,
syntax: ‘< – längd-andel>’,
initialValue: ‘0%’
});

CSS.registerProperty({
namn: ‘–c0’,
syntax: ‘<färg>’,
initialValue: “röd”
});

/* samma för-c1 */

Vi använder samma animation som tidigare positionen för den första stop –pos och, utöver detta, vi införa två steg() animeringar för de andra två variablerna, byta deras värden varje gång en iteration av den första animering (en att ändra värdet för –pos) är klar:

$t: 1s;

html {
/* samma som innan */
animation: en 0s oändlig;
animation-namn: c0, pos, c1;
animation-längd: 2*$t $t;
animation-timing-funktion: steg(1), ease-in-out;
}

@keyframes pos {{ –pos: 100%; } }

@keyframes c0 { 50% { –c0: #{n: te($c, 2)} } }
@keyframes c1 { 50% { –c1: #{n: te($c, 1)} } }

Och vi får följande resultat:

En annan version av persienner animation (live demo, Blink webbläsare med flagga).

Vi kan också använda denna till en radial gradient() (inget men bakgrunden deklaration ändringar):

bakgrund: radial gradient(circle, var(–c0) var(–pos, 0%), var(–c1), 0);

Växande skivor (live demo, Blink webbläsare med flagga).

Exakt samma taktik som fungerar för kon-gradient ():

bakgrund: kon-gradient(var(–c0) var(–pos, 0%), var(–c1), 0);

Växande segment (live demo, Blink webbläsare med flagga).

Upprepa gradienter är också en möjlighet att skapa en krusning-liknande effekt i radiell fall:

$p: 2em;

html {
/* samma som innan */
bakgrund: upprepa-radial gradient(circle,
var(–c0) 0 var(–pos, 0px), var(–c1) 0 $s);
}

@keyframes pos { 90%, 100% { –pos: #{$p} } }

Ringar (live demo, Blink webbläsare med flagga).

Och en helix/strålar effekt i den koniska fall:

$p: 5 procent.

html {
/* samma som innan */
bakgrund: upprepa-konisk-gradient(
var(–c0) 0 var(–pos, 0%), var(–c1) 0 $s);
}

@keyframes pos { 90%, 100% { –pos: #{$p} } }

Växande strålar (live demo, Blink webbläsare med flagga).

Vi kan också lägga till en annan CSS-variabel för att göra saker mer intressanta:

$n: 20;

html {
/* samma som innan */
bakgrund: radial gradient(cirkeln var(–o, 50% 50%),
var(–c0) var(–pos, 0%), var(–c1), 0);
animation: en 0s oändlig;
animation-namn: c0, o, pos, c1;
animation-längd: 2*$t $n*$t $t;
animation-timing-funktion: steg(1), steg(1), ease-in-out;
}

@keyframes o {
@$jag från 0 till $n {
#{$i*100%/$n} { –o: #{random(100)*1%} #{random(100)*1%} }
}
}

Vi måste registrera dig för denna variabel för att det hela ska fungera:

CSS.registerProperty({
namn: –o,
syntax: ‘< – längd-andel>+’,
initialValue: ’50 procent”
});

Och det är det! Resultatet kan ses nedan:

Slumpmässigt placerad växande skivor (live demo, Blink webbläsare med flagga).

Jag skulle säga att framtiden för att ändra gradienter med nyckelruta animationer ser ganska cool ut. Men under tiden, för cross-browser-lösningar, JavaScript sätt förblir den enda giltiga.

Jetpack WordPress plugin som körs på denna webbplats, driver inte bara relaterade inlägg nedan, men säkerhet och backup, Wiki-stöd, sök på sajten, kommentera form, sociala nätverk, och mycket mer!