CSS Infinite 3D Sliders PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

CSS Infinite 3D Sliders

I denne serien, har vi laget bildeglidere uten annet enn HTML og CSS. Tanken er at vi kan bruke samme markering, men forskjellig CSS for å få helt forskjellige resultater, uansett hvor mange bilder vi kaster inn. Vi startet med en sirkulær skyveknapp som roterer uendelig, på en måte som en fidget-spinner som holder bilder. Så har vi laget en som blar gjennom en bunke bilder.

Denne gangen dykker vi inn i den tredje dimensjonen. Det kommer til å se tøft ut til å begynne med, men mye av koden vi ser på er akkurat det vi brukte i de to første artiklene i denne serien, med noen modifikasjoner. Så hvis du akkurat nå er i gang med serien, vil jeg foreslå at du sjekker ut de andre for kontekst på konseptene vi bruker her.

CSS Sliders-serien

Dette er det vi sikter mot:

Ved første øyekast ser det ut som vi har en roterende kube med fire bilder. Men i virkeligheten har vi å gjøre med seks bilder totalt. Her er glidebryteren fra en annen vinkel:

Nå som vi har et godt bilde for hvordan bildene er ordnet, la oss dissekere koden for å se hvordan vi kommer dit.

Grunnoppsettet

Samme HTML som resten av glidebryterne vi har brukt for de andre skyvekontrollene:

Og nok en gang bruker vi CSS Grid for å plassere bildene i en stabel, den ene oppå den andre:

.gallery {
  display: grid;
}
.gallery > img {
  grid-area: 1 / 1;
  width: 160px;
  aspect-ratio: 1;
  object-fit: cover;
}

Animasjonen

Logikken for denne glideren er veldig lik den sirkulære glidebryteren fra den første artikkelen. Faktisk, hvis du sjekker videoen ovenfor på nytt, kan du se at bildene er plassert på en måte som skaper en polygon. Etter en full rotasjon går den tilbake til det første bildet.

Vi stolte på CSS transform-origin og animation-delay egenskaper for den første glidebryteren. Den samme animasjonen brukes på alle bildeelementene, som roterer rundt samme punkt. Deretter, ved å bruke forskjellige forsinkelser, plasserer vi alle bildene riktig rundt en stor sirkel.

Implementeringen vil være litt annerledes for vår 3D-glidebryter. Ved hjelp av transform-origin vil ikke fungere her fordi vi jobber i 3D, så vi vil bruke transform i stedet for å plassere alle bildene riktig, roter deretter beholderen.

Vi strekker oss etter Sass igjen slik at vi kan gå gjennom antall bilder og bruke transformasjonene våre:

@for $i from 1 to ($n + 1) {
  .gallery > img:nth-child(#{$i}) {
     transform: 
       rotate(#{360*($i - 1) / $n}deg) /* 1 */
       translateY(50% / math.tan(180deg / $n)) /* 2 */ 
       rotateX(90deg); /* 3 */
  }
}

Du lurer kanskje på hvorfor vi hopper rett inn i Sass. Vi startet med et fast antall bilder ved å bruke vanilla CSS i de andre artiklene før vi generaliserte koden med Sass for å ta hensyn til et hvilket som helst tall (N) av bilder. Vel, jeg tror du forstår ideen nå, og vi kan kutte ut alt det oppdagelsesarbeidet for å komme til den virkelige implementeringen.

De transform eiendom tar tre verdier, som jeg har illustrert her:

CSS Infinite 3D Sliders

Vi roterer først alle bildene over hverandre. Rotasjonsvinkelen avhenger av antall bilder. Til N bilder, har vi en økning lik 360deg/N. Da vi translate alle bildene i samme mengde på en måte som gjør at midtpunktene møtes på sidene.

Viser stabelen med bilder arrangert flatt i en sirkel med en rød linje som går gjennom midten av bildene.
CSS Infinite 3D Sliders

Det er litt kjedelig geometri som hjelper til med å forklare hvordan alt dette fungerer, men avstanden er lik 50%/tan(180deg/N). Vi behandlet en lignende ligning når vi laget den sirkulære skyveknappen ( transform-origin: 50% 50%/sin(180deg/N) ).

Til slutt roterer vi bildene rundt x-aksen med 90deg for å få den ordningen vi ønsker. Her er en video som illustrerer hva den siste rotasjonen gjør:

Nå er alt vi trenger å gjøre å rotere hele beholderen for å lage vår uendelige glidebryter.

.gallery {
  transform-style: preserve-3d;
  --_t: perspective(280px) rotateX(-90deg);
  animation: r 12s cubic-bezier(.5, -0.2, .5, 1.2) infinite;
}
@keyframes r {
  0%, 3% {transform: var(--_t) rotate(0deg); }
  @for $i from 1 to $n {
    #{($i/$n)*100 - 2}%, 
    #{($i/$n)*100 + 3}% {
      transform: var(--_t) rotate(#{($i / $n) * -360}deg);
    }  
  }
  98%, 100% { transform: var(--_t) rotate(-360deg); }
}

Den koden kan være vanskelig å forstå, så la oss faktisk gå tilbake et øyeblikk og gå tilbake til animasjonen vi laget for den sirkulære glidebryteren. Dette er hva vi skrev i den første artikkelen:

.gallery {
  animation: m 12s cubic-bezier(.5, -0.2, .5, 1.2) infinite;
}
@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); }
}

Keyframes er nesten identiske. Vi har samme prosentverdier, samme løkke og samme rotasjon.

Hvorfor er begge de samme? Fordi deres logikk er den samme. I begge tilfeller er bildene arrangert rundt en sirkulær form, og vi må rotere hele greia for å vise hvert bilde. Det var slik jeg var i stand til å kopiere nøkkelbildene fra den sirkulære skyveknappen og bruke den samme koden for 3D-glidebryteren vår. Den eneste forskjellen er at vi må rotere beholderen med -90deg langs x-aksen for å se bildene siden vi allerede har rotert dem med 90deg på samme akse. Så legger vi et snev av perspective for å få 3D-effekten.

Det er det! Skyveknappen vår er ferdig. Her er hele demoen igjen. Alt du trenger å gjøre er å legge til så mange bilder du vil og oppdatere én variabel for å få det i gang.

Vertikal 3D-glidebryter

Siden vi spiller i 3D-rommet, hvorfor ikke lage en vertikal versjon av den forrige glidebryteren? Den siste roterer langs z-aksen, men vi kan også bevege oss langs x-aksen om vi vil.

Hvis du sammenligner koden for begge versjonene av denne glidebryteren, vil du kanskje ikke umiddelbart oppdage forskjellen fordi det bare er ett tegn! jeg erstattet rotate() med rotateX() inne i keyframes og bildet transform. Det er det!

Det bør bemerkes at rotate() tilsvarer rotateZ(), så ved å endre aksen fra Z til X vi forvandler glidebryteren fra den horisontale versjonen til den vertikale.

Kubeglider

Vi kan ikke snakke om 3D i CSS uten snakker om kuber. Og ja, det betyr at vi skal lage en annen versjon av glidebryteren.

Ideen bak denne versjonen av glidebryteren er å lage en faktisk kubeform med bildene og rotere hele tingen rundt den forskjellige aksen. Siden det er en kube, har vi å gjøre med seks ansikter. Vi bruker seks bilder, ett for hver side av kuben. Så, ingen Sass, men tilbake til vanilla CSS.

Den animasjonen er litt overveldende, ikke sant? Hvor begynner du i det hele tatt?

Vi har seks ansikter, så vi må utføre minst seks rotasjoner slik at hvert bilde får en tur. Vel, faktisk trenger vi fem rotasjoner - den siste bringer oss tilbake til det første bildeansiktet. Hvis du tar tak i en Rubiks kube – eller en annen kubeformet gjenstand som terninger – og roterer den med hånden, vil du ha en god ide om hva vi gjør.

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

  transform-style: preserve-3d;
  --_p: perspective(calc(2.5*var(--s)));
  animation: r 9s infinite cubic-bezier(.5, -0.5, .5, 1.5);
}

@keyframes r {
  0%, 3%   { transform: var(--_p); }
  14%, 19% { transform: var(--_p) rotateX(90deg); }
  31%, 36% { transform: var(--_p) rotateX(90deg) rotateZ(90deg); }
  47%, 52% { transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg); }
  64%, 69% { transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg) rotateX(90deg); }
  81%, 86% { transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg) rotateX(90deg) rotateZ(90deg); }
  97%, 100%{ transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg) rotateX(90deg) rotateZ(90deg) rotateY(-90deg); }
}

De transform egenskap starter med null rotasjoner, og i hver tilstand legger vi til en ny rotasjon på en bestemt akse til vi når seks rotasjoner. Da er vi tilbake til det første bildet.

La oss ikke glemme plasseringen av bildene våre. Hver og en påføres en side av kuben ved hjelp av transform:

.gallery img {
  grid-area: 1 / 1;
  width: var(--s);
  aspect-ratio: 1;
  object-fit: cover;
  transform: var(--_t,) translateZ(calc(var(--s) / 2));
}
.gallery img:nth-child(2) { --_t: rotateX(-90deg); }
.gallery img:nth-child(3) { --_t: rotateY( 90deg) rotate(-90deg); }
.gallery img:nth-child(4) { --_t: rotateX(180deg) rotate( 90deg); }
.gallery img:nth-child(5) { --_t: rotateX( 90deg) rotate( 90deg); }
.gallery img:nth-child(6) { --_t: rotateY(-90deg); }

Du tenker nok at det er merkelig kompleks logikk bak verdiene jeg bruker der, ikke sant? Vel nei. Alt jeg gjorde var å åpne DevTools og leke med forskjellige rotasjonsverdier for hvert bilde til jeg fikk det riktig. Det høres kanskje dumt ut, men hei, det fungerer - spesielt siden vi har et fast antall bilder og vi ikke ser etter noe som støtter N bilder.

Glem faktisk verdiene jeg bruker og prøv å gjøre plasseringen på egen hånd som en øvelse. Start med alle bildene stablet oppå hverandre, åpne DevTools, og gå! Du vil sannsynligvis ende opp med en annen kode, og det er helt greit. Det kan være forskjellige måter å plassere bildene på.

Hva er trikset med kommaet inni var()? Er det en skrivefeil?

Det er ikke en skrivefeil, så ikke fjern den! Hvis du fjerner det, vil du legge merke til at det påvirker plasseringen av det første bildet. Du kan se det i koden min jeg definerte --_t for alle bildene unntatt det første fordi jeg bare trenger en oversettelse for det. Det kommaet gjør at variabelen faller tilbake til en nullverdi. Uten kommaet vil vi ikke ha en reserve, og hele verdien vil være ugyldig.

Fra spesifikasjonen:

Merk: Det vil si var(--a,) er en gyldig funksjon, som spesifiserer at hvis --a egendefinert egenskap er ugyldig eller mangler var()` bør erstattes med ingenting.

Tilfeldig kubeglider

Litt tilfeldighet kan være en fin forbedring for denne typen animasjoner. Så i stedet for å rotere kuben i rekkefølge, kan vi kaste terningen så å si, og la kuben rulle slik den vil.

Kult ikke sant? Jeg vet ikke med deg, men jeg liker denne versjonen bedre! Det er mer interessant og overgangene er tilfredsstillende å se på. Og gjett hva? Du kan leke med verdiene for å lage din egen tilfeldige kubeglidebryter!

Logikken er faktisk ikke tilfeldig i det hele tatt - det ser bare slik ut. Du definerer en transform på hver keyframe som lar deg vise ett ansikt og … vel, det er det virkelig! Du kan velge hvilken som helst bestilling du vil.

@keyframes r {
  0%, 3%   { transform: var(--_p) rotate3d( 0, 0, 0,  0deg); }
  14%,19%  { transform: var(--_p) rotate3d(-1, 1, 0,180deg); }
  31%,36%  { transform: var(--_p) rotate3d( 0,-1, 0, 90deg); }
  47%,52%  { transform: var(--_p) rotate3d( 1, 0, 0, 90deg); }
  64%,69%  { transform: var(--_p) rotate3d( 1, 0, 0,-90deg); }
  81%,86%  { transform: var(--_p) rotate3d( 0, 1, 0, 90deg); }
  97%,100% { transform: var(--_p) rotate3d( 0, 0, 0,  0deg); }
}

Jeg bruker rotate3d() denne gangen, men jeg er fortsatt avhengig av DevTools for å finne verdiene som føles "riktige" for meg. Ikke prøv å finne et forhold mellom nøkkelbildene fordi det rett og slett ikke er en. Jeg definerer separate transformasjoner og ser deretter det "tilfeldige" resultatet. Sørg for at det første bildet er henholdsvis den første og siste rammen, og vis et annet bilde på hver av de andre rammene.

Du er ikke forpliktet til å bruke en rotate3d() transformere som jeg gjorde. Du kan også kjede forskjellige rotasjoner som vi gjorde i forrige eksempel. Lek og se hva du kan finne på! Jeg venter på at du skal dele din versjon med meg i kommentarfeltet!

Innpakning opp

Jeg håper du likte denne lille serien. Vi bygde noen morsomme (og morsomme) skyveknapper mens vi lærte mye om alle slags CSS-konsepter underveis – fra rutenettplassering og stablingsrekkefølge, til animasjonsforsinkelser og transformasjoner. Vi fikk til og med leke med en dash Sass for å gå gjennom en rekke elementer.

Og vi gjorde alt med nøyaktig samme HTML for hver skyveknapp vi laget. Hvor kult er det? CSS er veldig kraftig og i stand til å oppnå så mye uten hjelp av JavaScript.

Tidstempel:

Mer fra CSS triks