CSS Infinite and Circular Rotating Image Slider PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

CSS Infinite og Circular Rotating Image Slider

Bildeskyvere (også kalt karuseller) er overalt. Det er mange CSS-triks for å lage den vanlige glidebryteren hvor bildene glir fra venstre til høyre (eller motsatt). Det er samme avtale med de mange JavaScript-bibliotekene der ute som lager fancy skyveknapper med komplekse animasjoner. Vi kommer ikke til å gjøre noe av det i dette innlegget.

Gjennom en liten serie med artikler skal vi utforske noen fancy og uvanlige CSS-bare skyveknapper. Hvis du er lei av å se de samme gamle klassiske gliderne, så er du på rett sted!

CSS Sliders-serien

For denne første artikkelen vil vi starte med noe jeg kaller den "sirkulære roterende bildeglidebryteren":

Kult ikke sant? la oss dissekere koden!

HTML-markeringen

Hvis du fulgte serien min av fancy bildedekorasjoner or CSS-rutenett og tilpassede former, så vet du at min første regel er å jobbe med minst mulig HTML. Jeg prøver alltid hardt å finne CSS-løsninger før jeg roter koden min med mye

s og andre ting.

Den samme regelen gjelder her - koden vår er ikke annet enn en liste over bilder i en beholder.

La oss si at vi jobber med fire bilder:

Det er det! La oss nå gå til den interessante delen av koden. Men først skal vi dykke ned i dette for å forstå logikken i hvordan glidebryteren vår fungerer.

Hvordan virker det?

Her er en video hvor jeg fjerner overflow: hidden fra CSS slik at vi bedre kan forstå hvordan bildene beveger seg:

Det er som om de fire bildene våre er plassert på en stor sirkel som roterer mot klokken.

CSS Infinite og Circular Rotating Image Slider

Alle bildene har samme størrelse (angitt med S på figuren). Legg merke til den blå sirkelen som er sirkelen som skjærer midten av alle bildene og har en radius (R). Vi vil trenge denne verdien senere for animasjonen vår. R er lik 0.707 * S. (Jeg kommer til å hoppe over geometrien som gir oss den ligningen.)

La oss skrive litt CSS!

Vi bruker CSS-rutenett for å plassere alle bildene i samme område over hverandre:

.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;
}

Ingenting for komplisert så langt. Den vanskelige delen er animasjonen.

Vi snakket om å rotere en stor sirkel, men i virkeligheten vil vi rotere hvert bilde individuelt og skape en illusjon av en stor roterende sirkel. Så la oss definere en animasjon, m, og bruk det på bildeelementene:

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

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

Hovedtrikset er avhengig av den uthevede linjen. Som standard er CSS transform-origin eiendom er lik center (eller 50% 50%) som får bildet til å rotere rundt midten, men vi trenger det ikke for å gjøre det. Vi trenger at bildet roterer rundt midten av bildet stor sirkel som inneholder bildene våre, derav den nye verdien for transform-origin.

Siden R er lik 0.707 * S, kan vi si det R er lik 70.7% av bildestørrelsen. Her er en figur for å illustrere hvordan vi fikk det 120.7% verdi:

CSS Infinite and Circular Rotating Image Slider PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.
CSS Infinite og Circular Rotating Image Slider

La oss kjøre animasjonen og se hva som skjer:

Jeg vet jeg vet. Resultatet er langt fra det vi ønsker, men i realiteten er vi veldig nærme. Det kan se ut som det bare er ett bilde der, men ikke glem at vi har stablet alle bildene oppå hverandre. Alle roterer samtidig og bare det øverste bildet er synlig. Det vi trenger er å forsinke animasjonen av hvert bilde for å unngå denne overlappingen.

.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 */

Ting blir allerede bedre!

Hvis vi skjuler overløpet på beholderen, kan vi allerede se en glidebryter, men vi vil oppdatere animasjonen litt slik at hvert bilde forblir synlig i en kort periode før det beveger seg.

Vi skal oppdatere animasjonsnøkkelframene våre for å gjøre nettopp det:

@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); }
}

For hver 90deg (360deg/4, Hvor 4 er antall bilder) legger vi til en liten pause. Hvert bilde vil forbli synlig for 5% av den totale varigheten før vi glir til neste (27%-22%, 52%-47%, etc.). Jeg skal oppdatere animation-timing-function ved hjelp av en cubic-bezier() funksjon for å gjøre animasjonen litt mer avansert:

Nå er glideren vår perfekt! Vel, nesten perfekt fordi vi fortsatt mangler den siste touchen: den fargerike sirkulære kanten som roterer rundt bildene våre. Vi kan bruke et pseudo-element på .gallery innpakning for å lage det:

.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);
}

Jeg har laget en sirkel med en repeterende konisk gradient for bakgrunnen mens du bruker en maskeringstriks som bare viser det polstrede området. Så bruker jeg den samme animasjonen som vi definerte for bildene.

Vi er ferdige! Vi har en kul sirkulær skyveknapp:

La oss legge til flere bilder

Å jobbe med fire bilder er bra, men det ville vært bedre om vi kan skalere det til et hvilket som helst antall bilder. Tross alt er dette formålet med en bildeglidebryter. Vi bør kunne vurdere N bilder.

For dette skal vi gjøre koden mer generisk ved å introdusere Sass. Først definerer vi en variabel for antall bilder ($n) og vi vil oppdatere hver del der vi har hardkodet antall bilder (4).

La oss starte med forsinkelsene:

.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 */

Formelen for forsinkelsen er (1 - $i)*duration/$n, som gir oss følgende Sass-løkke:

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

Vi kan også gjøre varigheten til en variabel hvis vi virkelig ønsker det. Men la oss gå videre til animasjonen:

@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); }
}

La oss forenkle det for å få en bedre oversikt over mønsteret:

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

Trinnet mellom hver stat er lik 25% - som er 100%/4 - og vi legger til en -90deg vinkel - som er -360deg/4. Det betyr at vi kan skrive løkken vår slik i stedet:

@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); }
}

Siden hvert bilde tar 5% av animasjonen endrer vi dette:

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

…med dette:

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

Det bør bemerkes at 5% er en vilkårlig verdi jeg velger for dette eksemplet. Vi kan også gjøre det til en variabel for å kontrollere hvor mye tid hvert bilde skal forbli synlig. Jeg kommer til å hoppe over det for enkelhets skyld, men for lekser kan du prøve å gjøre det og dele implementeringen din i kommentarfeltet!

@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); }
}

Den siste biten er å oppdatere transform-origin. Vi trenger noen geometritriks. Uansett antall bilder, er konfigurasjonen alltid den samme. Vi har bildene våre (små sirkler) plassert inne i en stor sirkel, og vi må finne verdien av radiusen, R.

CSS Infinite and Circular Rotating Image Slider PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.
CSS Infinite og Circular Rotating Image Slider

Du vil sannsynligvis ikke ha en kjedelig geometriforklaring, så her er hvordan vi finner R:

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

Hvis vi uttrykker det i prosent, gir det oss:

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

…som betyr transform-origin verdien er lik:

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

Vi er ferdige! Vi har en skyveknapp som fungerer med alle tallbilder!

La oss kaste ni bilder der:

Legg til så mange bilder du vil og oppdater $n variabel med totalt antall bilder.

Innpakning opp

Med noen få triks ved å bruke CSS-transformasjoner og standardgeometri, laget vi en fin sirkulær glidebryter som ikke krever mye kode. Det som er kult med denne glidebryteren er at vi ikke trenger å plage å duplisere bildene for å beholde den uendelige animasjonen siden vi har en sirkel. Etter en full rotasjon kommer vi tilbake til det første bildet!

Tidstempel:

Mer fra CSS triks