Controles deslizantes 3D infinitos de CSS | trucos 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 CSS diferente para obtener resultados muy diferentes sin importar cuántas imágenes le arrojemos. Comenzamos con un control deslizante circular que gira sin cesar, como una especie de rueda giratoria que contiene imágenes. Luego hicimos uno que se desplaza a través de 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 viendo es exactamente el mismo que usamos en los dos primeros artículos de esta serie, con algunas modificaciones. Por lo tanto, si es nuevo en la serie, le sugiero que consulte a los demás para conocer el contexto de los conceptos que estamos usando aquí.
Esto es lo que buscamos:
A primera vista, parece que tenemos un cubo giratorio con cuatro imágenes. Pero en realidad estamos ante un total de seis imágenes. 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 vamos a llegar allí.
el escenario principal
El mismo HTML que el resto de los controles deslizantes que hemos usado para los otros controles deslizantes:
<div class="gallery">
<img src="" alt="">
<img src="" alt="">
<img src="" alt="">
<img src="" alt="">
<img src="" alt="">
</div>
Y nuevamente usamos CSS Grid para apilar las imágenes una encima de la 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 al 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 CSS transform-origin
y animation-delay
propiedades para este primer control deslizante. La misma animación se aplica a todos los elementos de la imagen que giran alrededor del mismo punto. Luego, usando diferentes retrasos, colocamos correctamente todas las imágenes alrededor de un gran círculo.
La implementación será ligeramente diferente para nuestro control deslizante 3D transform-origin
no funcionará aquí porque estamos trabajando en 3D, así que usaremos transform
En lugar de colocar todas las imágenes correctamente, gire el contenedor.
Nuevamente, buscamos Sass para poder recorrer el conteo 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é nos metemos directamente en Sass. Comenzamos con un número fijo de imágenes usando el CSS estándar en los otros artículos antes de envolver el código con Sass para dar cuenta de un número arbitrario (N
) a partir 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.
los transform
La propiedad toma tres valores, que he ilustrado aquí:
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 una ganancia igual a 360deg/N
. que nosotros translate
todas las imágenes con la misma cantidad de manera que sus puntos centrales se encuentren con los lados.
Hay una geometría aburrida que ayuda a explicar cómo funciona todo esto, pero la distancia es igual a 50%/tan(180deg/N)
Estábamos tratando 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 con 90deg
para conseguir el arreglo que queremos. Aquí hay un video que ilustra lo que hace el último giro:
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); }
}
Este código puede ser difícil de entender, así que retrocedamos un poco 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 porcentajes, el mismo ciclo y el mismo giro.
¿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í es como pude copiar los fotogramas clave del control deslizante circular y usamos el mismo código para nuestro control deslizante 3D. La única diferencia es que necesitamos rotar el contenedor con -90deg
a lo largo del eje x para ver las imágenes ya que las rotamos 90deg
en el mismo eje. Luego añadimos un toque de perspective
para conseguir un efecto 3D.
¡Está! 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 las dos versiones de este control deslizante, es posible que no note inmediatamente la diferencia porque es solo un carácter. reemplacé rotate()
con rotateX()
dentro de los fotogramas clave y la imagen transform
. ¡Está!
se debe notar que rotate()
es equivalente a rotateZ()
entonces cambiando el eje de Z
a X
Transformamos el control deslizante de una versión horizontal a una vertical.
Control deslizante cúbico
No podemos hablar de 3D en CSS sin hablar 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 rotar todo alrededor de un eje diferente. Como se trata de 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.
Esta animación es un poco abrumadora, ¿no? ¿Por dónde empiezas?
Tenemos seis caras, por lo que debemos realizar al menos seis rotaciones para que cada imagen gire. Bueno, en realidad necesitamos cinco rotaciones; la última nos devuelve a la primera cara de la imagen. Si tomas un cubo de Rubik, o algún otro objeto con forma de cubo, como un dado, y lo haces girar con la mano, tendrás 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); }
}
los transform
La propiedad comienza con cero rotaciones y a cada estado le agregamos una nueva rotación a lo largo de un eje específico hasta llegar a seis rotaciones. Luego volvemos a la primera imagen.
No olvidemos la colocación de nuestras imágenes. Cada uno se aplica a la 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és pensando que hay una extraña lógica complicada 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 tonto, pero bueno, funciona, especialmente porque tenemos un número fijo de imágenes y no estamos buscando algo que admita N
imágenes
De hecho, olvídese de los valores que estoy usando e intente hacer la colocación usted mismo 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á perfectamente 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?
Esto 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 eso en mi código que definí --_t
para todas las imágenes excepto la primera porque solo necesito una traducción para ella. Esta coma hace que la variable vuelva a tener un valor nulo. Sin la coma, no tendremos respaldo y el valor completo no será válido.
Nota: es decir
var(--a,)
es una función válida que indica que si--a
propiedad personalizada no es válida o falta, elvar()
` 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 tirar el cubo en orden secuencial, podemos tirar los dados, por así decirlo, y dejar que el cubo ruede como quiera.
Genial, ¿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 no es realmente aleatoria en absoluto, solo parece ser así. transform
en cada fotograma clave que te permite mostrar una cara y... bueno, ¡eso es todo! Puede elegir cualquier fila.
@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); }
}
yo suelo rotate3d()
esta vez, pero todavía confío en DevTools para encontrar los valores que me parecen "correctos". No intente encontrar una conexión entre los fotogramas clave porque simplemente no la hay. Defino transformaciones separadas y luego miro el resultado "aleatorio".Asegúrate de que la primera imagen sea el primer y último cuadro respectivamente y muestre una imagen diferente en cada uno de los otros cuadros.
Usted no tiene la obligación de usar un rotate3d()
transformar como yo lo hice. También puedes vincular 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!
resumiendo
Esperamos que hayas disfrutado de esta pequeña serie. Hemos creado algunos controles deslizantes divertidos (y divertidos), mientras aprendemos mucho sobre todo tipo de conceptos de CSS en el camino, desde el diseño de la cuadrícula y el orden de la pila, hasta los retrasos y transformaciones de animación. Incluso pudimos jugar con Sass Dash para recorrer una variedad de elementos.
Y lo hicimos todo con exactamente el mismo HTML para cada control deslizante que hicimos. ¿Qué tan asombroso es eso? CSS es increíblemente poderoso y capaz de lograr mucho sin la ayuda de JavaScript.
Deja una respuesta