CSS Infinite ja pyöreä pyörivä kuvan liukusäädin

Lähdesolmu: 1765846

Kuvan liukusäätimiä (kutsutaan myös karuselleiksi) on kaikkialla. Siellä on paljon CSS-temppuja yhteisen liukusäätimen luomiseksi jossa kuvat liukuvat vasemmalta oikealle (tai päinvastoin). Se on sama sopimus monet JavaScript-kirjastot jotka luovat hienoja liukusäätimiä monimutkaisilla animaatioilla. Emme aio tehdä mitään tästä tässä viestissä.

Pienen artikkelisarjan avulla aiomme tutkia joitain hienoja ja harvinaisia ​​vain CSS-liukusäätimiä. Jos olet kyllästynyt näkemään samoja vanhoja klassisia liukusäätimiä, olet oikeassa paikassa!

CSS Sliders -sarja

Tässä ensimmäisessä artikkelissa aloitamme jollakin, jota kutsun "pyöreäksi pyöriväksi kuvan liukusäätimeksi":

Siistiä eikö? tutkitaan koodia!

HTML-merkintä

Jos seurasit sarjaani hienoja kuvakoristeita or CSS-ruudukko ja mukautetut muodot, niin tiedät, että ensimmäinen sääntöni on työskennellä pienimmällä mahdollisella HTML-koodilla. Yritän aina kovasti löytää CSS-ratkaisuja ennen kuin sotkeen koodiani paljon

s ja muut tavarat.

Sama sääntö pätee tässäkin - koodimme on vain luettelo säilössä olevista kuvista.

Oletetaan, että työskentelemme neljän kuvan kanssa:

Se siitä! Siirrytään nyt koodin mielenkiintoiseen osaan. Mutta ensin sukeltamme tähän ymmärtääksemme liukusäätimemme toiminnan logiikan.

Miten tämä toimii?

Tässä on video, josta poistan overflow: hidden CSS:stä, jotta voimme paremmin ymmärtää, miten kuvat liikkuvat:

On kuin neljä kuvaamme olisi asetettu suurelle ympyrälle, joka pyörii vastapäivään.

Kaikki kuvat ovat samankokoisia (merkitty S kuvassa). Huomaa sininen ympyrä, joka on ympyrä, joka leikkaa kaikkien kuvien keskustan ja jonka säde (R). Tarvitsemme tätä arvoa myöhemmin animaatiossamme. R on yhtä suuri kuin 0.707 * S. (Aion ohittaa geometrian, joka antaa meille tämän yhtälön.)

Kirjoitetaan vähän CSS:ää!

Me käytämme CSS-ruudukko sijoittaaksesi kaikki kuvat samalle alueelle päällekkäin:

.gallery  {
  --s: 280px; /* control the size */

  display: grid;
  width: var(--s);
  aspect-ratio: 1;
  padding: calc(var(--s) / 20); /* we will see the utility of this later */
  border-radius: 50%;
}
.gallery > img {
  grid-area: 1 / 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}

Ei mitään liian monimutkaista toistaiseksi. Hankalin osa on animaatio.

Puhuimme suuren ympyrän pyörittämisestä, mutta todellisuudessa pyöritämme jokaista kuvaa yksitellen luoden illuusion suuresta pyörivästä ympyrästä. Joten määritellään animaatio, mja käytä sitä kuvaelementteihin:

.gallery > img {
  /* same as before */
  animation: m 8s infinite linear;
  transform-origin: 50% 120.7%;
}

@keyframes m {
  100% { transform: rotate(-360deg); }
}

Päätemppu perustuu tuohon korostettuun riviin. Oletuksena CSS transform-origin omaisuus on yhtä suuri kuin center (Tai 50% 50%), joka saa kuvan pyörimään keskipisteensä ympäri, mutta emme tarvitse sitä siihen. Tarvitsemme kuvan pyörivän kuvan keskustan ympäri iso ympyrä joka sisältää kuvamme, joten uusi arvo transform-origin.

Koska R on yhtä suuri kuin 0.707 * S, voimme sanoa sen R on yhtä suuri kuin 70.7% kuvan koosta. Tässä on kuva, joka havainnollistaa, kuinka saimme sen 120.7% arvo:

Suoritetaan animaatio ja katsotaan mitä tapahtuu:

Tiedän tiedän. Tulos on kaukana siitä, mitä haluamme, mutta todellisuudessa olemme hyvin lähellä. Saattaa näyttää siltä, ​​että siellä on vain yksi kuva, mutta älä unohda, että olemme pinottaneet kaikki kuvat päällekkäin. Ne kaikki pyörivät samaan aikaan ja vain yläkuva on näkyvissä. Meidän on viivästettävä kunkin kuvan animaatiota päällekkäisyyden välttämiseksi.

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

Asiat ovat jo paranemassa!

Jos piilotamme ylivuodon säiliössä, näemme jo liukusäätimen, mutta päivitämme animaatiota hieman, jotta jokainen kuva pysyy näkyvissä hetken ennen kuin se liikkuu eteenpäin.

Päivitämme animaation avainkehyksemme tehdäksemme juuri tämän:

@keyframes m {
  0%, 3% { transform: rotate(0); }
  22%, 27% { transform: rotate(-90deg); }
  47%, 52% { transform: rotate(-180deg); }
  72%, 77% { transform: rotate(-270deg); }
  98%, 100% { transform: rotate(-360deg); }
}

Kunkin 90deg (360deg/4, Jossa 4 on kuvien määrä) lisäämme pienen tauon. Jokainen kuva pysyy näkyvissä 5% kokonaiskestosta ennen kuin siirrymme seuraavaan (27%-22%, 52%-47%, jne.). Aion päivittää animation-timing-function käyttämällä cubic-bezier() toiminto, joka tekee animaatiosta hieman komeamman:

Nyt liukusäätimemme on täydellinen! No, melkein täydellinen, koska meiltä puuttuu vielä viimeinen silaus: värikäs pyöreä reunus, joka pyörii kuviemme ympärillä. Voimme käyttää pseudoelementtiä .gallery kääre sen tekemiseen:

.gallery {
  padding: calc(var(--s) / 20); /* the padding is needed here */
  position: relative;
}
.gallery::after {
  content: "";
  position: absolute;
  inset: 0;
  padding: inherit; /* Inherits the same padding */
  border-radius: 50%;
  background: repeating-conic-gradient(#789048 0 30deg, #DFBA69 0 60deg);
  mask: 
    linear-gradient(#fff 0 0) content-box, 
    linear-gradient(#fff 0 0);
  mask-composite: exclude;
}
.gallery::after,
.gallery >img {
  animation: m 8s infinite cubic-bezier(.5, -0.2, .5, 1.2);
}

Olen luonut ympyrän, jossa on a toistuva kartiogradientti taustalle, kun käytät a naamiointitemppu joka näyttää vain pehmustetun alueen. Sitten käytän siihen samaa animaatiota, jonka määritimme kuville.

Olemme valmiita! Meillä on siisti pyöreä liukusäädin:

Lisätään lisää kuvia

Neljän kuvan työstäminen on hyvä asia, mutta olisi parempi, jos voisimme skaalata sen mihin tahansa kuvien määrään. Loppujen lopuksi tämä on kuvan liukusäätimen tarkoitus. Meidän pitäisi pystyä harkitsemaan N kuvia.

Tätä varten aiomme tehdä koodista yleisemmän ottamalla käyttöön Sassin. Ensin määritetään muuttuja kuvien määrälle ($n) ja päivitämme jokaisen osan, johon koodasimme kuvien määrän (4).

Aloitetaan viiveistä:

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

Viiveen kaava on (1 - $i)*duration/$n, joka antaa meille seuraavan Sass-silmukan:

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

Voimme tehdä myös kestosta muuttujan, jos todella haluamme. Mutta siirrytään animaatioon:

@keyframes m {
  0%, 3% { transform: rotate(0); }
  22%, 27% { transform: rotate(-90deg); }
  47%, 52% { transform: rotate(-180deg); }
  72%, 77% { transform: rotate(-270deg); }
  98%, 100% {transform: rotate(-360deg); }
}

Yksinkertaistamme sitä saadaksesi paremman kuvan mallista:

@keyframes m {
  0% { transform: rotate(0); }
  25% { transform: rotate(-90deg); }
  50% { transform: rotate(-180deg); }
  75% { transform: rotate(-270deg); }
  100% { transform: rotate(-360deg); }
}

Kunkin tilan välinen askel on yhtä suuri 25% - mikä on 100%/4 - ja lisäämme a -90deg kulma - mikä on -360deg/4. Tämä tarkoittaa, että voimme kirjoittaa silmukamme seuraavasti:

@keyframes m {
  0% { transform: rotate(0); }
  @for $i from 1 to $n {
    #{($i / $n) * 100}% { transform: rotate(#{($i / $n) * -360}deg); }  
  }
  100% { transform: rotate(-360deg); }
}

Koska jokainen kuva ottaa 5% animaatiosta muutamme tämän:

#{($i / $n) * 100}%

…tämän kanssa:

#{($i / $n) * 100 - 2}%, #{($i / $n) * 100 + 3}%

On syytä huomata, että 5% on mielivaltainen arvo, jonka valitsen tälle esimerkille. Voimme myös tehdä siitä muuttujan, joka ohjaa, kuinka kauan kunkin kuvan tulee pysyä näkyvissä. Ohitan sen yksinkertaisuuden vuoksi, mutta kotitehtäviä varten voit yrittää tehdä sen ja jakaa toteutuksen kommenteissa!

@keyframes m {
  0%,3% { transform: rotate(0); }
  @for $i from 1 to $n {
    #{($i / $n) * 100 - 2}%, #{($i / $n) * 100 + 3}% { transform: rotate(#{($i / $n) * -360}deg); }  
  }
  98%,100% { transform: rotate(-360deg); }
}

Viimeinen osa on päivittäminen transform-origin. Tarvitsemme geometrisia temppuja. Kuvien määrästä riippumatta kokoonpano on aina sama. Kuvamme (pienet ympyrät) on sijoitettu suuren ympyrän sisään ja meidän on löydettävä säteen arvo, R.

Et luultavasti halua tylsää geometrian selitystä, joten löydämme näin R:

R = S / (2 * sin(180deg / N))

Jos ilmaisemme sen prosentteina, saamme:

R = 100% / (2 * sin(180deg / N)) = 50% / sin(180deg / N)

…joka tarkoittaa transform-origin arvo on yhtä suuri kuin:

transform-origin: 50% (50% / math.sin(180deg / $n) + 50%);

Olemme valmiit! Meillä on liukusäädin, joka toimii minkä tahansa numerokuvan kanssa!

Laitetaanpa sinne yhdeksän kuvaa:

Lisää niin monta kuvaa kuin haluat ja päivitä $n muuttuja kuvien kokonaismäärän mukaan.

Käärimistä

Muutamalla temppulla käyttämällä CSS-muunnoksia ja standardigeometriaa loimme mukavan pyöreän liukusäätimen, joka ei vaadi paljon koodia. Hienoa tässä liukusäätimessä on se, että meidän ei tarvitse vaivautua kopioimaan kuvia säilyttääksemme äärettömän animaation, koska meillä on ympyrä. Täyden kierroksen jälkeen palaamme ensimmäiseen kuvaan!

Aikaleima:

Lisää aiheesta CSS-temppuja