CSS Infinite 3D Sliders PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

Controles deslizantes 3D infinitos de CSS

En esta serie, hemos estado creando controles deslizantes de imágenes con nada más que HTML y CSS. La idea es que podemos usar el mismo marcado pero un CSS diferente para obtener resultados muy diferentes, sin importar cuántas imágenes arrojemos. Comenzamos con un control deslizante circular que gira infinitamente, como una especie de rueda giratoria que contiene imágenes. Luego hicimos uno que hojea una pila de fotos.

Esta vez, nos sumergimos en la tercera dimensión. Parecerá difícil al principio, pero gran parte del código que estamos analizando es exactamente el mismo que usamos en los dos primeros artículos de esta serie, con algunas modificaciones. Por lo tanto, si acaba de ingresar a la serie, le sugiero que consulte a los demás para conocer el contexto de los conceptos que estamos usando aquí.

Serie de controles deslizantes CSS

Esto es lo que buscamos:

A primera vista, parece que tenemos un cubo giratorio con cuatro imágenes. Pero en realidad, estamos tratando con seis imágenes en total. Aquí está el control deslizante desde un ángulo diferente:

Ahora que tenemos una buena visualización de cómo se organizan las imágenes, analicemos el código para ver cómo llegamos allí.

La configuración básica

El mismo HTML que el resto de los controles deslizantes que hemos usado para los otros controles deslizantes:

Y una vez más, estamos usando CSS Grid para colocar las imágenes en una pila, una encima de otra:

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

La animación

La lógica de este control deslizante es muy similar a el control deslizante circular del primer artículo. De hecho, si revisas el video de arriba nuevamente, puedes ver que las imágenes están colocadas de una manera que crea un polígono. Después de una rotación completa, vuelve a la primera imagen.

Confiamos en el CSS transform-origin y animation-delay propiedades para ese primer control deslizante. La misma animación se aplica a todos los elementos de la imagen, que giran alrededor del mismo punto. Luego, utilizando diferentes retrasos, colocamos correctamente todas las imágenes alrededor de un gran círculo.

La implementación será un poco diferente para nuestro control deslizante 3D. Usando transform-origin no funcionará aquí porque estamos trabajando en 3D, así que usaremos transform en lugar de colocar correctamente todas las imágenes, luego gire el contenedor.

Estamos buscando Sass nuevamente para poder recorrer la cantidad de imágenes y aplicar nuestras transformaciones:

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

Quizás se pregunte por qué estamos saltando directamente a Sass. Comenzamos con un número fijo de imágenes usando CSS estándar en los otros artículos antes de generalizar el código con Sass para dar cuenta de cualquier número (N) de imágenes. Bueno, creo que ya entendiste la idea y podemos eliminar todo ese trabajo de descubrimiento para llegar a la implementación real.

La transform La propiedad está tomando tres valores, que he ilustrado aquí:

Controles deslizantes 3D infinitos de CSS

Primero rotamos todas las imágenes una encima de la otra. El ángulo de rotación depende del número de imágenes. Para N imágenes, tenemos un incremento igual a 360deg/N. Entonces nosotros translate todas las imágenes en la misma cantidad de manera que sus puntos centrales se encuentren a los lados.

Mostrando la pila de imágenes dispuestas planas en un círculo con una línea roja que atraviesa el punto central de las imágenes.
Controles deslizantes 3D infinitos de CSS

Hay una geometría aburrida que ayuda a explicar cómo funciona todo esto, pero la distancia es igual a 50%/tan(180deg/N). Tratamos con una ecuación similar al hacer el control deslizante circular ( transform-origin: 50% 50%/sin(180deg/N) ).

Finalmente, rotamos las imágenes alrededor del eje x por 90deg para conseguir el arreglo que queremos. Aquí hay un video que ilustra lo que está haciendo la última rotación:

Ahora todo lo que tenemos que hacer es rotar todo el contenedor para crear nuestro control deslizante 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); }
}

Ese código puede ser difícil de entender, así que retrocedamos un momento y revisemos la animación que hicimos para el control deslizante circular. Esto es lo que escribimos en ese primer artículo:

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

Los fotogramas clave son casi idénticos. Tenemos los mismos valores porcentuales, el mismo bucle y la misma rotación.

¿Por qué ambos son iguales? Porque su lógica es la misma. En ambos casos, las imágenes están dispuestas alrededor de una forma circular y necesitamos rotar todo para mostrar cada imagen. Así fue como pude copiar los fotogramas clave del control deslizante circular y usar ese mismo código para nuestro control deslizante 3D. La única diferencia es que necesitamos rotar el contenedor por -90deg a lo largo del eje x para ver las imágenes ya que las hemos rotado por 90deg en el mismo eje. Luego añadimos un toque de perspective para conseguir el efecto 3D.

¡Eso es todo! Nuestro control deslizante está listo. Aquí está la demostración completa de nuevo. Todo lo que tiene que hacer es agregar tantas imágenes como desee y actualizar una variable para que funcione.

Control deslizante 3D vertical

Ya que estamos jugando en el espacio 3D, ¿por qué no hacer una versión vertical del control deslizante anterior? El último gira a lo largo del eje z, pero también podemos movernos a lo largo del eje x si queremos.

Si compara el código de ambas versiones de este control deslizante, es posible que no detecte inmediatamente la diferencia porque es solo un carácter. reemplacé rotate() rotateX() dentro de los fotogramas clave y la imagen transform. ¡Eso es!

Cabe señalar que rotate() es equivalente a rotateZ(), por lo que al cambiar el eje de Z a X transformamos el control deslizante de la versión horizontal a la vertical.

Control deslizante de cubo

No podemos hablar de 3D en CSS sin hablando de cubos. Y sí, eso significa que vamos a hacer otra versión del control deslizante.

La idea detrás de esta versión del control deslizante es crear una forma de cubo real con las imágenes y girar todo alrededor de los diferentes ejes. Como es un cubo, estamos tratando con seis caras. Usaremos seis imágenes, una para cada cara del cubo. Entonces, no Sass, pero volvamos a Vanilla CSS.

Esa animación es un poco abrumadora, ¿verdad? ¿Por dónde empiezas?

Tenemos seis caras, por lo que debemos realizar al menos seis rotaciones para que cada imagen tenga un giro. Bueno, en realidad, necesitamos cinco rotaciones; la última nos lleva de vuelta a la primera cara de la imagen. Si toma un cubo de Rubik, o algún otro objeto con forma de cubo, como un dado, y lo gira con la mano, tendrá una buena idea de lo que estamos haciendo.

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

La transform La propiedad comienza con cero rotaciones y, en cada estado, agregamos una nueva rotación en un eje específico hasta llegar a seis rotaciones. Entonces volvemos a la primera imagen.

No olvidemos la colocación de nuestras imágenes. Cada uno se aplica a una cara del cubo usando 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); }

Probablemente esté pensando que hay una extraña lógica compleja detrás de los valores que estoy usando allí, ¿verdad? Bueno no. Todo lo que hice fue abrir DevTools y jugar con diferentes valores de rotación para cada imagen hasta que lo hice bien. Puede sonar estúpido, pero funciona, especialmente porque tenemos un número fijo de imágenes y no estamos buscando algo que admita N imágenes.

De hecho, olvide los valores que estoy usando e intente hacer la colocación por su cuenta como un ejercicio. Comience con todas las imágenes apiladas una encima de la otra, abra DevTools y listo. Probablemente terminará con un código diferente y eso está totalmente bien. Puede haber diferentes maneras de colocar las imágenes.

¿Cuál es el truco con la coma dentro del var()? ¿Es un error tipográfico?

¡No es un error tipográfico, así que no lo elimines! Si lo elimina, notará que afecta la ubicación de la primera imagen. Puedes ver que en mi código definí --_t para todas las imágenes excepto la primera porque solo necesito una traducción para ella. Esa coma hace que la variable regrese a un valor nulo. Sin la coma, no tendremos un respaldo y el valor total no será válido.

Desde la especificación:

Nota: Es decir, var(--a,) es una función válida, especificando que si el --a propiedad personalizada no es válida o falta, el var()` debe ser reemplazado por nada.

Deslizador de cubo aleatorio

Un poco de aleatoriedad puede ser una buena mejora para este tipo de animación. Entonces, en lugar de rotar el cubo en orden secuencial, podemos tirar los dados, por así decirlo, y dejar que el cubo ruede como quiera.

¿Guay, verdad? No sé ustedes, ¡pero a mí me gusta más esta versión! Es más interesante y las transiciones son satisfactorias de ver. ¿Y adivina qué? ¡Puedes jugar con los valores para crear tu propio control deslizante de cubo aleatorio!

La lógica es real, no aleatoria en absoluto, simplemente parece ser así. Tú defines un transform en cada fotograma clave que te permite mostrar una cara y... bueno, ¡eso es todo! Puedes elegir el pedido que quieras.

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

Estoy utilizando rotate3d() esta vez, pero sigo confiando en DevTools para encontrar los valores que me parecen "correctos". No intente encontrar una relación entre los fotogramas clave porque simplemente no existe. Estoy definiendo transformaciones separadas y luego viendo el resultado "aleatorio". Asegúrese de que la primera imagen sea el primer y el último fotograma, respectivamente, y muestre una imagen diferente en cada uno de los otros fotogramas.

No está obligado a utilizar un rotate3d() transformarme como lo hice yo. También puedes encadenar diferentes rotaciones como hicimos en el ejemplo anterior. ¡Juega y mira lo que se te ocurre! ¡Te estaré esperando para compartir tu versión conmigo en la sección de comentarios!

Terminando

Espero que hayas disfrutado de esta pequeña serie. Creamos algunos controles deslizantes divertidos (y divertidos) mientras aprendíamos mucho sobre todo tipo de conceptos de CSS en el camino, desde la ubicación de la cuadrícula y el orden de apilamiento, hasta los retrasos y transformaciones de animación. Incluso pudimos jugar con una pizca de Sass para recorrer una variedad de elementos.

Y lo hicimos todo con exactamente el mismo HTML para todos y cada uno de los controles deslizantes que creamos. ¿Cuan genial es eso? CSS es muy poderoso y capaz de lograr mucho sin la ayuda de JavaScript.

Sello de tiempo:

Mas de Trucos CSS