CSS Infiniti cursori 3D PlatoBlockchain Data Intelligence. Ricerca verticale. Ai.

Cursori 3D infiniti CSS

In questa serie, abbiamo realizzato cursori di immagini con nient'altro che HTML e CSS. L'idea è che possiamo utilizzare lo stesso markup ma CSS diversi per ottenere risultati estremamente diversi, indipendentemente dal numero di immagini che inseriamo. Abbiamo iniziato con un dispositivo di scorrimento circolare che ruota all'infinito, una specie di spinner fidget che contiene immagini. Poi ne abbiamo realizzato uno che sfoglia una pila di foto.

Questa volta, ci stiamo tuffando nella terza dimensione. All'inizio sembrerà difficile, ma gran parte del codice che stiamo esaminando è esattamente quello che abbiamo usato nei primi due articoli di questa serie, con alcune modifiche. Quindi, se stai entrando nella serie solo ora, ti suggerisco di dare un'occhiata agli altri per un contesto sui concetti che stiamo usando qui.

Serie di cursori CSS

Questo è ciò a cui miriamo:

A prima vista, sembra che abbiamo un cubo rotante con quattro immagini. Ma in realtà abbiamo a che fare con sei immagini in totale. Ecco il cursore da un'angolazione diversa:

Ora che abbiamo una buona visuale di come sono disposte le immagini, analizziamo il codice per vedere come ci arriviamo.

La configurazione di base

Stesso codice HTML del resto degli slider che abbiamo utilizzato per gli altri slider:

E ancora una volta, stiamo usando CSS Grid per posizionare le immagini in una pila, una sopra l'altra:

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

L'animazione

La logica di questo dispositivo di scorrimento è molto simile a il cursore circolare del primo articolo. Infatti, se controlli di nuovo il video qui sopra, puoi vedere che le immagini sono posizionate in modo da creare un poligono. Dopo una rotazione completa, ritorna alla prima immagine.

Ci siamo affidati al CSS transform-origin ed animation-delay proprietà per quel primo dispositivo di scorrimento. La stessa animazione viene applicata a tutti gli elementi dell'immagine, che ruotano attorno allo stesso punto. Quindi, utilizzando diversi ritardi, posizioniamo correttamente tutte le immagini attorno a un grande cerchio.

L'implementazione sarà leggermente diversa per il nostro dispositivo di scorrimento 3D. Usando transform-origin non funzionerà qui perché stiamo lavorando in 3D, quindi useremo transform invece per posizionare correttamente tutte le immagini, ruotare il contenitore.

Stiamo raggiungendo di nuovo Sass in modo da poter scorrere il numero di immagini e applicare le nostre trasformazioni:

@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 */
  }
}

Forse ti starai chiedendo perché stiamo saltando direttamente su Sass. Abbiamo iniziato con un numero fisso di immagini utilizzando Vanilla CSS negli altri articoli prima di generalizzare il codice con Sass per tenere conto di qualsiasi numero (N) di immagini. Bene, penso che tu abbia capito ora e possiamo eliminare tutto quel lavoro di scoperta per arrivare alla vera implementazione.

Il transform property assume tre valori, che ho illustrato qui:

Cursori 3D infiniti CSS

Per prima cosa ruotiamo tutte le immagini una sopra l'altra. L'angolo di rotazione dipende dal numero di immagini. Per N immagini, abbiamo un incremento pari a 360deg/N. Quindi noi translate tutte le immagini della stessa quantità in modo che i loro punti centrali si incontrino sui lati.

Mostra la pila di immagini disposte in piano in un cerchio con una linea rossa che attraversa il punto centrale delle immagini.
Cursori 3D infiniti CSS

C'è una geometria noiosa che aiuta a spiegare come funziona tutto questo, ma la distanza è uguale a 50%/tan(180deg/N). Abbiamo affrontato un'equazione simile durante la creazione del dispositivo di scorrimento circolare ( transform-origin: 50% 50%/sin(180deg/N) ).

Infine, ruotiamo le immagini attorno all'asse x di 90deg per ottenere l'accordo che vogliamo. Ecco un video che illustra cosa sta facendo l'ultima rotazione:

Ora tutto ciò che dobbiamo fare è ruotare l'intero contenitore per creare il nostro cursore infinito.

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

Quel codice potrebbe essere difficile da capire, quindi facciamo un passo indietro e rivisitiamo l'animazione che abbiamo creato per il cursore circolare. Questo è ciò che abbiamo scritto in quel primo articolo:

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

I fotogrammi chiave sono quasi identici. Abbiamo gli stessi valori percentuali, lo stesso loop e la stessa rotazione.

Perché sono entrambi uguali? Perché la loro logica è la stessa. In entrambi i casi, le immagini sono disposte attorno a una forma circolare e dobbiamo ruotare il tutto per mostrare ogni immagine. È così che sono stato in grado di copiare i fotogrammi chiave dal cursore circolare e utilizzare lo stesso codice per il nostro cursore 3D. L'unica differenza è che dobbiamo ruotare il contenitore di -90deg lungo l'asse x per vedere le immagini poiché le abbiamo già ruotate di 90deg sullo stesso asse. Quindi aggiungiamo un tocco di perspective per ottenere l'effetto 3D.

Questo è tutto! Il nostro dispositivo di scorrimento è terminato. Ecco di nuovo la demo completa. Tutto quello che devi fare è aggiungere tutte le immagini che vuoi e aggiornare una variabile per farlo funzionare.

Cursore verticale 3D

Dato che stiamo giocando nello spazio 3D, perché non creare una versione verticale del cursore precedente? L'ultimo ruota lungo l'asse z, ma possiamo anche spostarci lungo l'asse x se lo vogliamo.

Se confronti il ​​codice per entrambe le versioni di questo dispositivo di scorrimento, potresti non notare immediatamente la differenza perché è solo un carattere! ho sostituito rotate() con rotateX() all'interno dei fotogrammi chiave e dell'immagine transform. Questo è tutto!

Essendo un sito serio, rotate() è equivalente rotateZ(), quindi cambiando l'asse da Z a X trasformiamo lo slider dalla versione orizzontale a quella verticale.

Cursore cubo

Non possiamo parlare di 3D in CSS senza parlando di cubi. E sì, significa che realizzeremo un'altra versione dello slider.

L'idea alla base di questa versione del dispositivo di scorrimento è quella di creare una vera forma di cubo con le immagini e ruotare l'intera cosa attorno al diverso asse. Dato che è un cubo, abbiamo a che fare con sei facce. Useremo sei immagini, una per ogni faccia del cubo. Quindi, niente Sass ma torniamo al CSS vanigliato.

Quell'animazione è un po' travolgente, vero? Da dove inizi?

Abbiamo sei facce, quindi dobbiamo eseguire almeno sei rotazioni in modo che ogni immagine abbia una svolta. Bene, in realtà, abbiamo bisogno di cinque rotazioni: l'ultima ci riporta alla prima faccia dell'immagine. Se vai a prendere un cubo di Rubik - o qualche altro oggetto a forma di cubo come i dadi - e lo ruoti con la mano, avrai una buona idea di cosa stiamo facendo.

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

Il transform property inizia con zero rotazioni e, su ogni stato, aggiungiamo una nuova rotazione su un asse specifico fino a raggiungere sei rotazioni. Quindi torniamo alla prima immagine.

Non dimentichiamo il posizionamento delle nostre immagini. Ciascuno viene applicato a una faccia del cubo utilizzando 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); }

Probabilmente stai pensando che ci sia una strana logica complessa dietro i valori che sto usando lì, giusto? Beh no. Tutto quello che ho fatto è stato aprire DevTools e giocare con diversi valori di rotazione per ogni immagine finché non ho capito bene. Può sembrare stupido ma, ehi, funziona, soprattutto perché abbiamo un numero fisso di immagini e non stiamo cercando qualcosa che supporti N immagini.

In effetti, dimentica i valori che sto usando e prova a fare il posizionamento da solo come esercizio. Inizia con tutte le immagini impilate una sopra l'altra, apri DevTools e via! Probabilmente ti ritroverai con un codice diverso e va benissimo. Ci possono essere diversi modi per posizionare le immagini.

Qual è il trucco con la virgola all'interno del file var()? È un errore di battitura?

Non è un errore di battitura quindi non rimuoverlo! Se lo rimuovi, noterai che influisce sul posizionamento della prima immagine. Puoi vederlo nel mio codice che ho definito --_t per tutte le immagini tranne la prima perché mi serve solo una traduzione. Quella virgola fa ricadere la variabile su un valore nullo. Senza la virgola, non avremo un fallback e l'intero valore non sarà valido.

Da la specifica:

Nota: cioè, var(--a,) è una funzione valida, specificando che se il --a proprietà personalizzata non è valida o mancante, il var()` dovrebbe essere sostituito con niente.

Cursore cubo casuale

Un po' di casualità può essere un bel miglioramento per questo tipo di animazione. Quindi, piuttosto che ruotare il cubo in ordine sequenziale, possiamo tirare i dadi per così dire, e lasciare che il cubo rotoli come vuole.

Bello vero? Non so voi, ma a me questa versione piace di più! È più interessante e le transizioni sono soddisfacenti da guardare. E indovina cosa? Puoi giocare con i valori per creare il tuo cursore cubo casuale!

La logica non è affatto casuale, sembra solo così. Tu definisci un transform su ogni fotogramma chiave che ti permette di mostrare una faccia e... beh, è ​​proprio così! Puoi scegliere qualsiasi ordine tu voglia.

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

Sto usando rotate3d() questa volta, ma mi affido ancora a DevTools per trovare i valori che mi sembrano "giusti". Non cercare di trovare una relazione tra i fotogrammi chiave perché semplicemente non ce n'è uno. Sto definendo trasformazioni separate e poi guardando il risultato "casuale". Assicurati che la prima immagine sia rispettivamente il primo e l'ultimo fotogramma e mostri un'immagine diversa su ciascuno degli altri fotogrammi.

Non sei obbligato a utilizzare a rotate3d() trasformare come ho fatto io. Puoi anche concatenare diverse rotazioni come abbiamo fatto nell'esempio precedente. Gioca e guarda cosa riesci a inventare! Ti aspetto per condividere la tua versione con me nella sezione commenti!

Concludendo

Spero che questa piccola serie vi sia piaciuta. Abbiamo creato alcuni cursori divertenti (e divertenti) mentre imparavamo molto su tutti i tipi di concetti CSS lungo il percorso, dal posizionamento della griglia e l'ordine di sovrapposizione, ai ritardi e alle trasformazioni dell'animazione. Abbiamo anche avuto modo di giocare con un pizzico di Sass per passare in rassegna una serie di elementi.

E abbiamo fatto tutto con lo stesso codice HTML per ogni slider che abbiamo creato. Quant'è fico? I CSS sono dannatamente potenti e in grado di realizzare così tanto senza l'aiuto di JavaScript.

Timestamp:

Di più da Trucchi CSS