CSS Infinite Slider Prelistava slike Polaroid PlatoBlockchain Data Intelligence. Navpično iskanje. Ai.

Neskončni drsnik CSS, ki lista po polaroidnih slikah

V zadnjem članku, smo naredili zelo kul majhen drsnik (ali "vrtiljak", če vam je to ljubše), ki se vrti v krožni smeri. Tokrat bomo naredili takšno, ki bo prelistala kup polaroidnih slik.

Kul kajne? Ne glejte še kode, ker je treba marsikaj razvozlati. Pridruži se mi, boš?

Serija drsnikov CSS

Osnovna postavitev

Večina HTML in CSS za ta drsnik je podobna krožnemu drsniku, ki smo ga naredili zadnjič. Pravzaprav uporabljamo popolnoma enake oznake:

In to je osnovni CSS, ki določa našega starša .gallery vsebnik kot mreža, kjer so vse slike zložene ena na drugo:

.gallery  {
  display: grid;
  width: 220px; /* controls the size */
}
.gallery > img {
  grid-area: 1 / 1;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border: 10px solid #f2f2f2;
  box-shadow: 0 0 4px #0007;
}

Zaenkrat nič zapletenega. Tudi za slog, podoben Polaroidu za slike, uporabljam samo nekaj border in box-shadow. Morda bi to lahko storili bolje, zato se lahko poigrate s temi okrasnimi slogi! Večino pozornosti bomo namenili animaciji, ki je najtežji del.

Kaj je trik?

Logika tega drsnika je odvisna od vrstnega reda zlaganja slik – tako da, igrali se bomo z z-index. Vse slike se začnejo z istim z-index vrednost (2), kar bo logično zadnja slika na vrhu sklada.

Vzamemo zadnjo sliko in jo potisnemo v desno, dokler ne razkrije naslednje slike v nizu. Nato pomanjšamo sliko z-index vrednosti, nato pa ga potisnemo nazaj v krov. In od svojega z-index nižja od vrednosti preostalih slik, postane zadnja slika v nizu.

Tukaj je slečena predstavitev, ki prikazuje trik. Premaknite miškin kazalec na sliko, da aktivirate animacijo:

Zdaj pa si predstavljajte, da se isti trik uporabi za vse slike. Tukaj je vzorec, če uporabljamo :nth-child() psevdoizbirnik za razlikovanje slik:

  • Pomaknemo zadnjo sliko (N). Naslednja slika je vidna (N - 1).
  • Pomaknemo naslednjo sliko (N - 1). Naslednja slika je vidna (N - 2)
  • Pomaknemo naslednjo sliko (N - 2). Naslednja slika je vidna (N - 3)
  • (Nadaljujemo z istim postopkom, dokler ne pridemo do prve slike)
  • Pomaknemo prvo sliko (1). Zadnja slika (N) je spet viden.

To je naš neskončni drsnik!

Razčlenitev animacije

Če se spomnite prejšnjega članka, sem definiral samo eno animacijo in se igral z zakasnitvami za nadzor vsake slike. Enako bomo počeli tukaj. Poskusimo si najprej vizualizirati časovnico naše animacije. Začeli bomo s tremi slikami, nato jih posplošili za poljubno število (N) slik.

Neskončni drsnik CSS, ki lista po polaroidnih slikah

Naša animacija je razdeljena na tri dele: »drsi v desno«, »drsi v levo« in »ne premikaj se«. Z lahkoto prepoznamo zamik med vsako sliko. Če upoštevamo, da se prva slika začne pri 0s, trajanje pa je enako 6s, potem se bo drugi začel ob -2s in tretji pri -4s.

.gallery > img:nth-child(2) { animation-delay: -2s; } /* -1 * 6s / 3 */
.gallery > img:nth-child(3) { animation-delay: -4s; } /* -2 * 6s / 3 */

Vidimo lahko tudi, da del »ne premikaj se« zavzame dve tretjini celotne animacije (2*100%/3), medtem ko dela »drs v desno« in »drs v levo« skupaj zavzameta eno tretjino — torej je vsak enak 100%/6 celotne animacije.

Ključne okvirje animacije lahko zapišemo takole:

@keyframes slide {
  0%     { transform: translateX(0%); }
  16.67% { transform: translateX(120%); }
  33.34% { transform: translateX(0%); }
  100%   { transform: translateX(0%); } 
}

To 120% je poljubna vrednost. Potreboval sem nekaj večjega od 100%. Slike morajo zdrsniti v desno stran od ostalih slik. Za to se mora vsaj premakniti 100% njegove velikosti. Zato sem šel 120% — pridobiti nekaj dodatnega prostora.

Zdaj moramo razmisliti o z-index. Ne pozabite, da moramo posodobiti slike z-index vrednost po zdrsne desno od kupa in pred zdrsnemo nazaj na dno kupčka.

@keyframes slide {
  0%     { transform: translateX(0%);   z-index: 2; }
  16.66% { transform: translateX(120%); z-index: 2; }
  16.67% { transform: translateX(120%); z-index: 1; } /* we update the z-order here */
  33.34% { transform: translateX(0%);   z-index: 1; }
  100%   { transform: translateX(0% );  z-index: 1; }  
}

Namesto da bi definirali eno državo pri 16.67% (100%/6) na časovni premici definiramo dve stanji na skoraj identičnih točkah (16.66% in 16.67%) kje za z-index vrednost se zmanjša, preden sliko potisnemo nazaj na krov.

Evo, kaj se zgodi, ko vse to združimo:

Hmmm, zdi se, da drsni del dobro deluje, vendar je vrstni red zlaganja pomešan! Animacija se začne lepo, saj se zgornja slika premakne nazaj ... vendar naslednje slike ne sledijo temu. Če opazite, se druga slika v zaporedju vrne na vrh sklada, preden na njej utripa naslednja slika.

Pozorno moramo spremljati z-index spremembe. Na začetku so vse slike z-index: 2. To pomeni, da bi moral vrstni red zlaganja iti ...

Our eyes 👀 --> 3rd (2) | 2nd (2) | 1st (2)

Pomaknemo tretjo sliko in jo posodobimo z-index za pridobitev tega naročila:

Our eyes 👀 --> 2nd (2) | 1st (2) | 3rd (1)

Enako naredimo z drugim:

Our eyes 👀 --> 1st (2) | 3rd (1) | 2nd (1)

…in prvi:

Our eyes 👀 --> 3rd (1) | 2nd (1) | 1st (1)

To storimo in zdi se, da je vse v redu. A v resnici ni tako! Ko se prva slika premakne nazaj, bo tretja slika začela novo ponovitev, kar pomeni, da se vrne nazaj z-index: 2:

Our eyes 👀 --> 3rd (2) | 2nd (1) | 1st (1)

Torej v resnici nikoli nismo imeli vseh slik z-index: 2 nasploh! Ko se slike ne premikajo (tj. del animacije »ne premikaj se«), se z-index is 1. Če tretjo sliko potisnemo in jo posodobimo z-index vrednost od 2 do 1, bo ostal na vrhu! Ko imajo vse slike enake z-index, zadnja v izvornem vrstnem redu - naša tretja slika v tem primeru - je na vrhu sklada. Drsenje tretje slike povzroči naslednje:

Our eyes 👀 --> 3rd (1) | 2nd (1) | 1st (1)

Tretja slika je še vedno na vrhu in takoj za njo premaknemo drugo sliko na vrh, ko se njena animacija znova zažene ob z-index: 2:

Our eyes 👀 --> 2nd (2) | 3rd (1) | 1st (1)

Ko ga potisnemo, dobimo:

Our eyes 👀 --> 3rd (1) | 2nd (1) | 1st (1)

Nato bo prva slika skočila na vrh:

Our eyes 👀 --> 1st(2) | 3rd (1) | 2nd (1)

OK, izgubil sem se. Potem je vsa logika napačna?

Vem, zmedeno je. A naša logika ni popolnoma napačna. Samo malo moramo popraviti animacijo, da bo vse delovalo tako, kot želimo. Trik je v tem, da pravilno ponastavite z-index.

Vzemimo situacijo, ko je tretja slika na vrhu:

Our eyes 👀 -->  3rd (2) | 2nd (1) | 1st (1)

Videli smo drsenje tretje slike in njeno spreminjanje z-index ohranja na vrhu. Kar moramo storiti, je posodobiti z-index druge slike. Torej, preden tretjo sliko potisnemo stran od kompleta, posodobimo z-index druge slike do 2.

Z drugimi besedami, ponastavimo z-index druge slike, preden se animacija konča.

Diagramiranje delov animacije z indikatorji za povečanje ali zmanjšanje indeksa z.
Neskončni drsnik CSS, ki lista po polaroidnih slikah

Zeleni simbol plus predstavlja naraščanje z-index do 2, rdeči minus pa je povezan z z-index: 1. Druga slika se začne z z-index: 2, nato pa ga posodobimo na 1 ko zdrsne stran od krova. Toda preden prva slika zdrsne s krova, spremenimo z-index druge slike nazaj na 2. Tako boste zagotovili, da bosta obe sliki enaki z-index, vseeno pa bo tretji ostal na vrhu, ker se pojavi pozneje v DOM. Toda po tretji diapozitivi slike in to z-index se posodobi, se premakne na dno.

To dve tretjini skozi animacijo, zato ustrezno posodobimo naše ključne sličice:

@keyframes slide {
  0%     { transform: translateX(0%);   z-index: 2; }
  16.66% { transform: translateX(120%); z-index: 2; }
  16.67% { transform: translateX(120%); z-index: 1; } /* we update the z-order here */
  33.34% { transform: translateX(0%);   z-index: 1; }
  66.33% { transform: translateX(0%);   z-index: 1; }
  66.34% { transform: translateX(0%);   z-index: 2; } /* and also here */
  100%   { transform: translateX(0%);   z-index: 2; }  
}

Malo bolje, a še vedno ne precej tam. Obstaja še eno vprašanje ...

Oh ne, tega ne bo nikoli konec!

Ne skrbite, ne bomo več spreminjali ključnih sličic, ker se ta težava pojavi le, ko je vključena zadnja slika. Za zadnjo sliko lahko naredimo "posebno" animacijo ključnih sličic, da popravimo stvari.

Ko je prva slika na vrhu, imamo naslednjo situacijo:

Our eyes 👀 -->  1st (2) | 3rd (1) | 2nd (1)

Glede na prejšnjo prilagoditev, ki smo jo naredili, bo tretja slika skočila na vrh, preden bo zdrsnila prva slika. To se zgodi samo v tej situaciji, ker je naslednja slika, ki se premakne za prvo sliko zadnja slika, ki ima višji vrstni red v DOM. Ostale slike so v redu, ker jih imamo N, Potem N - 1, potem gremo od 3 do 2in 2 do 1… potem pa gremo od 1 do N.

Da bi se temu izognili, bomo za zadnjo sliko uporabili naslednje ključne sličice:

@keyframes slide-last {
  0%     { transform: translateX(0%);   z-index: 2;}
  16.66% { transform: translateX(120%); z-index: 2; }
  16.67% { transform: translateX(120%); z-index: 1; } /* we update the z-order here */
  33.34% { transform: translateX(0%);   z-index: 1; }
  83.33% { transform: translateX(0%);   z-index: 1; }
  83.34% { transform: translateX(0%);   z-index: 2; } /* and also here */
  100%   { transform: translateX(0%);   z-index: 2; }
}

Ponastavimo z-index vrednost 5/6 skozi animacijo (namesto dveh tretjin), kar je, ko je prva slika zunaj kupa. Torej ne vidimo nobenega skakanja!

TADA! Naš neskončni drsnik je zdaj popoln! Tukaj je naša končna koda v vsem svojem sijaju:

.gallery > img {
  animation: slide 6s infinite;
}
.gallery > img:last-child {
  animation-name: slide-last;
}
.gallery > img:nth-child(2) { animation-delay: -2s; } 
.gallery > img:nth-child(3) { animation-delay: -4s; }

@keyframes slide {
  0% { transform: translateX(0%); z-index: 2; }
  16.66% { transform: translateX(120%); z-index: 2; }
  16.67% { transform: translateX(120%); z-index: 1; } 
  33.34% { transform: translateX(0%); z-index: 1; }
  66.33% { transform: translateX(0%); z-index: 1; }
  66.34% { transform: translateX(0%); z-index: 2; } 
  100% { transform: translateX(0%); z-index: 2; }
}
@keyframes slide-last {
  0% { transform: translateX(0%); z-index: 2; }
  16.66% { transform: translateX(120%); z-index: 2; }
  16.67% { transform: translateX(120%); z-index: 1; }
  33.34% { transform: translateX(0%); z-index: 1; }
  83.33% { transform: translateX(0%); z-index: 1; }
  83.34% { transform: translateX(0%); z-index: 2; } 
  100%  { transform: translateX(0%); z-index: 2; }
}

Podpira poljubno število slik

Zdaj, ko naša animacija deluje za tri slike, naredimo, da deluje za poljubno število (N) slik. Toda najprej lahko svoje delo nekoliko optimiziramo tako, da razdelimo animacijo, da se izognemo odvečnosti:

.gallery > img {
  z-index: 2;
  animation: 
    slide 6s infinite,
    z-order 6s infinite steps(1);
}
.gallery > img:last-child {
  animation-name: slide, z-order-last;
}
.gallery > img:nth-child(2) { animation-delay: -2s; } 
.gallery > img:nth-child(3) { animation-delay: -4s; }

@keyframes slide {
  16.67% { transform: translateX(120%); }
  33.33% { transform: translateX(0%); }
}
@keyframes z-order {
  16.67%,
  33.33% { z-index: 1; }
  66.33% { z-index: 2; }
}
@keyframes z-order-last {
  16.67%,
  33.33% { z-index: 1; }
  83.33% { z-index: 2; }
}

Zdaj veliko manj kode! Naredimo eno animacijo za drsni del in drugo za z-index posodobitve. Upoštevajte, da uporabljamo steps(1) o z-index animacija. To je zato, ker želim nenadoma spremeniti z-index vrednost, za razliko od drsne animacije, kjer želimo gladko gibanje.

Zdaj, ko je kodo lažje brati in vzdrževati, imamo boljši pogled za ugotavljanje, kako podpreti poljubno število slik. Kar moramo storiti, je posodobiti zakasnitve animacije in odstotke ključnih sličic. Zakasnitev je enostavna, ker lahko uporabimo popolnoma isto zanko, ki smo jo naredili v prejšnjem članku, da podpremo več slik v krožnem drsniku:

@for $i from 2 to ($n + 1) {
  .gallery > img:nth-child(#{$i}) {
    animation-delay: calc(#{(1 - $i)/$n}*6s);
  }
}

To pomeni, da prehajamo z vanilije CSS na Sass. Nato si moramo predstavljati, kako meri časovnica N slike. Ne pozabimo, da animacija poteka v treh fazah:

Prikaz treh delov animacije v nizu vrstic s puščicami.
Neskončni drsnik CSS, ki lista po polaroidnih slikah

Po »drsu v desno« in »drsu v levo« mora slika ostati na mestu, dokler preostale slike ne gredo skozi zaporedje. Del »ne premikaj se« mora torej vzeti enako časa kot (N - 1) kot "drs v desno" in "drs v levo". In v eni ponovitvi, N slike bodo drsele. Torej, "drsi v desno" in "drsi v levo" oba 100%/N celotne časovnice animacije. Slika zdrsne stran od kupa pri (100%/N)/2 in zdrsne nazaj na 100%/N .

To lahko spremenimo:

@keyframes slide {
  16.67% { transform: translateX(120%); }
  33.33% { transform: translateX(0%); }
}

…za to:

@keyframes slide {
  #{50/$n}%  { transform: translateX(120%); }
  #{100/$n}% { transform: translateX(0%); }
}

Če zamenjamo N z 3, dobimo 16.67% in 33.33% ko obstajajo 3 slike v kupu. Ista logika je z vrstnim redom zlaganja, kjer bomo imeli to:

@keyframes z-order {
  #{50/$n}%,
  #{100/$n}% { z-index: 1; }
  66.33% { z-index: 2; }
}

Še vedno moramo posodobiti 66.33% točka. Tam naj bi se slika ponastavila z-index pred koncem animacije. Istočasno začne drseti naslednja slika. Ker drsni del traja 100%/N, bi se morala ponastavitev zgoditi ob 100% - 100%/N:

@keyframes z-order {
  #{50/$n}%,
  #{100/$n}% { z-index: 1; }
  #{100 - 100/$n}% { z-index: 2; }
}

Ampak za naše z-order-last animacija deluje, bi se moralo zgoditi nekoliko pozneje v zaporedju. Se spomnite popravka, ki smo ga naredili za zadnjo sliko? Ponastavitev z-index vrednost se mora zgoditi, ko je prva slika zunaj kupa in ne, ko začne drseti. Enako sklepanje lahko uporabimo tukaj v naših ključnih sličicah:

@keyframes z-order-last {
  #{50/$n}%,
  #{100/$n}% { z-index: 1; }
  #{100 - 50/$n}% { z-index: 2; }
}

Končali smo! Evo, kaj dobimo, če uporabimo pet slik:

Dodamo lahko kanček vrtenja, da naredimo stvari nekoliko bolj domiselne:

Vse, kar sem naredil, je dodal rotate(var(--r)) k transform premoženje. Znotraj zanke, --r je definiran z naključnim kotom:

@for $i from 1 to ($n + 1) {
  .gallery > img:nth-child(#{$i}) {
    --r: #{(-20 + random(40))*1deg}; /* a random angle between -20deg and 20deg */
  }
}

Vrtenje povzroča majhne napake, saj lahko včasih vidimo, da nekatere slike skočijo na zadnji del sklada, vendar to ni nič posebnega.

Zavijanje

Vse to z-index delo je bilo veliko ravnotežje, kajne? Če pred to vajo niste bili prepričani, kako deluje vrstni red zlaganja, potem imate zdaj verjetno veliko boljšo idejo! Če ste ugotovili, da je nekaterim razlagam težko slediti, vam toplo priporočam, da ponovno preberete članek in načrtujte stvari s svinčnikom in papirjem. Poskusite ilustrirati vsak korak animacije z različnim številom slik, da boste bolje razumeli trik.

Zadnjič smo uporabili nekaj geometrijskih trikov, da smo ustvarili krožni drsnik, ki se po celotnem zaporedju zavrti nazaj na prvo sliko. Tokrat smo izvedli podoben trik z uporabo z-index. V obeh primerih nismo podvojili nobene slike, da bi simulirali neprekinjeno animacijo, niti nismo posegli po JavaScriptu za pomoč pri izračunih.

Naslednjič bomo naredili 3D drsnike. Ostani na vezi!

Časovni žig:

Več od Triki CSS