CSS Infinite 3D Sliders PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

CSS Infinite 3D Sliders

I denna serie, vi har gjort bildskjutreglage med ingenting annat än HTML och CSS. Tanken är att vi kan använda samma uppmärkning men olika CSS för att få väldigt olika resultat, oavsett hur många bilder vi slänger in. Vi började med ett cirkulärt reglage som roterar oändligt, ungefär som en fidget spinner som håller bilder. Sedan gjorde vi en som bläddrar igenom en hög med bilder.

Den här gången dyker vi in ​​i den tredje dimensionen. Det kommer att se tufft ut till en början, men mycket av koden vi tittar på är precis vad vi använde i de två första artiklarna i den här serien, med vissa modifieringar. Så om du nyss börjar komma in i serien, skulle jag föreslå att du kollar in de andra för sammanhang om de koncept vi använder här.

CSS Sliders-serien

Det här är vad vi siktar på:

Vid första anblicken ser det ut som att vi har en roterande kub med fyra bilder. Men i verkligheten har vi att göra med sex bilder totalt. Här är reglaget från en annan vinkel:

Nu när vi har en bra bild för hur bilderna är ordnade, låt oss dissekera koden för att se hur vi kommer dit.

Grundinställningen

Samma HTML som resten av skjutreglagen vi har använt för de andra skjutreglagen:

Och återigen använder vi CSS Grid för att placera bilderna i en stack, en ovanpå en annan:

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

Animationen

Logiken för detta reglage är mycket lik det cirkulära reglaget från den första artikeln. Faktum är att om du kollar videon ovan igen kan du se att bilderna är placerade på ett sätt som skapar en polygon. Efter en hel rotation återgår den till den första bilden.

Vi litade på CSS transform-origin och animation-delay egenskaper för det första reglaget. Samma animering tillämpas på alla bildelement, som roterar runt samma punkt. Sedan, genom att använda olika fördröjningar, placerar vi alla bilder korrekt runt en stor cirkel.

Implementeringen kommer att vara lite annorlunda för vår 3D-skjutreglage. Använder sig av transform-origin kommer inte att fungera här eftersom vi arbetar i 3D, så vi kommer att använda transform istället för att placera alla bilder korrekt, rotera sedan behållaren.

Vi sträcker oss efter Sass igen så att vi kan gå igenom antalet bilder och tillämpa våra transformationer:

@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 kanske undrar varför vi hoppar rakt in i Sass. Vi började med ett fast antal bilder med vanilla CSS i de andra artiklarna innan vi generaliserade koden med Sass för att ta hänsyn till valfritt antal (N) av bilder. Nåväl, jag tror att du förstår idén nu och vi kan ta bort allt det där upptäcktsarbetet för att komma till den verkliga implementeringen.

Smakämnen transform egenskapen tar tre värden, som jag har illustrerat här:

CSS Infinite 3D Sliders

Vi roterar först alla bilderna ovanför varandra. Rotationsvinkeln beror på antalet bilder. För N bilder, har vi ett inkrement lika med 360deg/N. Då vi translate alla bilder i samma mängd på ett sätt som gör att deras mittpunkter möts på sidorna.

Visar högen med bilder placerade platt i en cirkel med en röd linje som löper genom bildernas mittpunkt.
CSS Infinite 3D Sliders

Det finns en del tråkig geometri som hjälper till att förklara hur allt detta fungerar, men avståndet är lika med 50%/tan(180deg/N). Vi hanterade en liknande ekvation när vi gjorde det cirkulära reglaget ( transform-origin: 50% 50%/sin(180deg/N) ).

Slutligen roterar vi bilderna runt x-axeln med 90deg för att få det arrangemang vi vill ha. Här är en video som illustrerar vad den senaste rotationen gör:

Nu behöver vi bara rotera hela behållaren för att skapa vårt oändliga reglage.

.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 vara svår att förstå, så låt oss faktiskt gå tillbaka ett ögonblick och återgå till animeringen vi gjorde för det cirkulära reglaget. Detta är vad vi skrev i den första artikeln:

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

Nyckelbildrutorna är nästan identiska. Vi har samma procentvärden, samma slinga och samma rotation.

Varför är båda desamma? För deras logik är densamma. I båda fallen är bilderna arrangerade runt en cirkulär form och vi måste rotera det hela för att visa varje bild. Det var så jag kunde kopiera nyckelbildrutorna från det cirkulära reglaget och använda samma kod för vårt 3D-reglage. Den enda skillnaden är att vi måste rotera behållaren förbi -90deg längs x-axeln för att se bilderna eftersom vi redan har roterat dem med 90deg på samma axel. Sedan lägger vi till en touch av perspective för att få 3D-effekten.

Det är allt! Vår reglage är klar. Här är hela demon igen. Allt du behöver göra är att lägga till så många bilder du vill och uppdatera en variabel för att få igång det.

Vertikal 3D-skjutreglage

Eftersom vi spelar i 3D-utrymmet, varför inte göra en vertikal version av det tidigare reglaget? Den sista roterar längs z-axeln, men vi kan också röra oss längs x-axeln om vi vill.

Om du jämför koden för båda versionerna av det här reglaget kanske du inte direkt ser skillnaden eftersom det bara är ett tecken! jag bytte ut rotate() med rotateX() inuti nyckelbildrutorna och bilden transform. Det är allt!

Det bör nämnas att rotate() är ekvivalent med rotateZ(), så genom att ändra axeln från Z till X vi förvandlar reglaget från den horisontella versionen till den vertikala.

Kubreglage

Vi kan inte prata om 3D i CSS utan pratar om kuber. Och ja, det betyder att vi kommer att göra en annan version av reglaget.

Tanken bakom den här versionen av skjutreglaget är att skapa en verklig kubform med bilderna och rotera hela grejen runt den olika axeln. Eftersom det är en kub har vi att göra med sex ansikten. Vi kommer att använda sex bilder, en för varje sida av kuben. Så, ingen Sass men tillbaka till vanilla CSS.

Den där animationen är lite överväldigande, eller hur? Var börjar man ens?

Vi har sex ansikten, så vi måste utföra minst sex rotationer så att varje bild får en tur. Tja, faktiskt, vi behöver fem rotationer - den sista tar oss tillbaka till den första bildens ansikte. Om du tar en Rubiks kub – eller något annat kubformat föremål som tärningar – och roterar den med handen, kommer du att ha en bra uppfattning om vad vi gö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); }
}

Smakämnen transform egenskapen börjar med nollrotationer och i varje tillstånd lägger vi till en ny rotation på en specifik axel tills vi når sex rotationer. Då är vi tillbaka till den första bilden.

Låt oss inte glömma placeringen av våra bilder. Var och en appliceras på en yta av kuben med hjälp 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 tror förmodligen att det finns en konstig komplex logik bakom de värden jag använder där, eller hur? Tja, nej. Allt jag gjorde var att öppna DevTools och leka med olika rotationsvärden för varje bild tills jag fick rätt. Det kanske låter dumt, men hey, det fungerar — speciellt eftersom vi har ett fast antal bilder och vi letar inte efter något som stöder N bilder.

I själva verket, glöm de värden jag använder och försök att göra placeringen på egen hand som en övning. Börja med alla bilder staplade ovanpå varandra, öppna DevTools och gå! Du kommer förmodligen att få en annan kod och det är helt okej. Det kan finnas olika sätt att placera bilderna på.

Vad är tricket med kommatecken inuti var()? Är det ett stavfel?

Det är inte ett stavfel så ta inte bort det! Om du tar bort den kommer du att märka att den påverkar placeringen av den första bilden. Du kan se det i min kod som jag definierade --_t för alla bilder utom den första eftersom jag bara behöver en översättning för den. Det kommatecken gör att variabeln faller tillbaka till ett nollvärde. Utan kommatecken kommer vi inte att ha en reserv och hela värdet kommer att vara ogiltigt.

Från specifikationen:

Obs: Det vill säga var(--a,) är en giltig funktion som anger att om --a anpassad egendom är ogiltig eller saknas, den var()` bör ersättas med ingenting.

Slumpmässig kubreglage

Lite slumpmässighet kan vara en trevlig förbättring för denna typ av animering. Så istället för att rotera kuben i sekventiell ordning, kan vi rulla tärningen så att säga, och låta kuben rulla hur den vill.

Coolt eller hur? Jag vet inte om dig, men jag gillar den här versionen bättre! Det är mer intressant och övergångarna är tillfredsställande att se. Och gissa vad? Du kan leka med värdena för att skapa din egen slumpmässiga kubskjutare!

Logiken är faktiskt inte slumpmässig alls - det verkar bara så. Du definierar a transform på varje nyckelbildruta som låter dig visa ett ansikte och... ja, det är verkligen det! Du kan välja vilken beställning du vill.

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

jag använder rotate3d() denna gång men jag litar fortfarande på DevTools för att hitta de värden som känns "rätt" för mig. Försök inte hitta en relation mellan nyckelbildrutorna eftersom det helt enkelt inte finns någon. Jag definierar separata transformationer och tittar sedan på det "slumpmässiga" resultatet. Se till att den första bilden är den första respektive den sista bildrutan, och visa en annan bild på var och en av de andra bildrutorna.

Du är inte skyldig att använda en rotate3d() förändras som jag gjorde. Du kan också kedja olika rotationer som vi gjorde i föregående exempel. Lek och se vad du kan hitta på! Jag väntar på att du ska dela din version med mig i kommentarsfältet!

Inslagning upp

Jag hoppas att ni gillade denna lilla serie. Vi byggde några roliga (och roliga) reglage samtidigt som vi lärde oss mycket om alla typer av CSS-koncept längs vägen — från rutnätsplacering och staplingsordning, till animeringsförseningar och transformationer. Vi fick till och med leka med en skvätt Sass för att gå igenom en rad element.

Och vi gjorde allt med exakt samma HTML för varje reglage vi gjorde. Hur coolt är inte det? CSS är väldigt kraftfullt och kan åstadkomma så mycket utan hjälp av JavaScript.

Tidsstämpel:

Mer från CSS-tricks