Prefacio
Cuando visité un determinado sitio web sin querer, me sentí profundamente atraído por el efecto carrusel en su página de inicio. A través de la depuración del navegador, finalmente entendí el principio de implementación y finalmente escribí una copia por mí mismo Demo
. El efecto final es el siguiente :( (El el código fuente está al final)
Efecto plano:
Efecto 3D:
Este carrusel corta la imagen en varias piezas, luego reproduce las piezas cortadas con efectos de animación a su vez y finalmente las une en una nueva imagen.
En el proceso de recuperación de la pila de tecnología front-end, parece que no existe ninguna tecnología que pueda recortar directamente la imagen y dividirla en varias partes, el efecto de recorte de imagen que solemos aplicar solo se utiliza canvas
para simular la generación.
A través de mi propia depuración, resulta que esta imagen de carrusel utiliza una canvas
forma más sencilla de lograr el mismo efecto de recorte.
A continuación, proceda de lo menos profundo a lo más profundo, paso a paso para revelar el principio de implementación.
Efecto plano
Comencemos con el efecto plano, primero escriba un html
diagrama de carrusel general , la estructura es la siguiente:
<div class="main" id="el">
<div class="item">
<img src="./img/1.jpg" />
</div>
<div class="item">
<img src="./img/2.jpg" />
</div>
<div class="item">
<img src="./img/3.jpg" />
</div>
</div>
el
Es el contenedor exterior, que contiene tres imágenes de carrusel.
Si queremos hacer un efecto de animación, tenemos que seguir un paso.
- Genera u obtén los
dom
elementos a animar dom
Agrega efectos de animación al elemento.
Ahora ralentice la animación del efecto plano y observe atentamente sus características, como se muestra en la siguiente figura:
html
Este segmento de imagen no se encuentra en el código original , lo que significa que los elementos que se van a animar deben ser generados por nosotros y agregados al documento de la página para su representación.
Si la imagen de configuración se cortará en 5
partes, entonces generamos una estructura de imagen de corte que es la siguiente:
<div class="main" id="el">
<div class="item">
<img src="./img/1.jpg" />
</div>
<div class="item">
<img src="./img/2.jpg" />
</div>
<div class="item">
<img src="./img/3.jpg" />
</div>
<!--做动画的dom元素-->
<div class="hook">
<div><img src="./img/2.jpg" /></div>
<div><img src="./img/2.jpg" /></div>
<div><img src="./img/2.jpg" /></div>
<div><img src="./img/2.jpg" /></div>
<div><img src="./img/2.jpg" /></div>
</div>
</div>
En la página original js
generando una clase llamada período hook
de html片段
, como modo de posicionamiento absolute
.
hook
Hay cinco div
, respectivamente, muestran 2.jpg
el correspondiente problema de corte foto enfrenta ahora es cómo hacer que este 5
se div
fuera a escalar esta imagen una parte de ella?
Si la configuración hook
del contenedor exterior tiene un ancho total del 1000px
subelemento, el 5
número div
promedio de 200px
puede ser proporcionado por un segundo, deje que div
solo muestre img
los segundos cortes.
<div style="position:absolute;width:200px;left:200px;overflow:hidden">
<img src="./img/2.jpg" style="position:absolute;width:500%;left:-200px"/>
</div>
Dado que el ancho total de la capa exterior 1000px
, corte en 5
partes que div
representan cada uno 200px
(en la codificación real a 200
través de js
calculado), y luego se mueve hacia la derecha 200px
ocupando la segunda posición de corte.
img
La asignación de la width
suma left
es el punto clave, y su valor específico también se calcula por el ancho total y el número de cortes.
width
Establezca en 500%
, lo que significa que el ancho de la imagen es igual al 1000px
contenedor más externo, y luego muévase hacia la izquierda 200px
. Debido a que el padre está div
establecido overflow:hidden
, imagine el efecto y saldrá.
Estos procesos mencionados anteriormente deben js
empalmarse y calcularse en una cadena html字符串
, similar a la siguiente:
for(i=0;i<n;i++){ //循环i次,n(总共将图片切成n份),unit_width对应每一个切块的宽度
html += `
<div
style="position:absolute;
width:${unit_width}px;
top:-100%;
left:${ i * unit_width};
overflow:hidden">
<img src="${src}"
style="position:absolute;
width:${n*100}%;
left:${-i * unit_width}px"/>
</div>
`
}
5
Después de div
completar la costura, colóquelo <div class="hook"></div>
y agréguelo a la representación del documento de la página. El dom
elemento final generado es el elemento que se animará a continuación.
Dado que se establece 5
un div
conjunto de posicionamiento y top
valor absolutos -100%
, una vez que se representan, se encuentran en la posición superior de la página.
El siguiente efecto de animación es muy fácil de lograr, solo necesitamos div
agregar uno a cada uno en el ciclo anterior transition:top linear 0.25s
.
Una vez que se completa 5
una div
representación, podemos js
establecer dinámicamente en cada uno div
de los top
valores de 0
animación que se activa, cada página div
se desliza lentamente hacia abajo desde la parte superior.
Espere hasta que se complete todo el proceso de animación, haremos que se elimine hook
este uso js
generado dom
, y que se debe mostrar item
(que contiene imágenes estáticas del original dom
) se configura para mostrar oculto desde este punto todo el proceso de animación se completa.
Efecto 3D
El efecto plano es relativamente sencillo de implementar y el 3D
efecto de volteo requiere primero una comprensión de css
los 3d
atributos.
Revisión de propiedad 3d
rotateX
: Alrededor del X
eje de rotación, Lenovo 单杠运动
.
rotateY
: Alrededor del Y
eje de rotación, Lenovo 钢管舞
.
rotateZ
: Alrededor del Z
eje de rotación, Lenovo 老式钟表盘
.
Los tres atributos anteriores generalmente se contactan mucho, por lo que no los repetiré. Lo siguiente se enfocará en los 3d
atributos.
.container{
perspective: 1200px;
perspective-origin: right center;
.wrapper {
transform-style: preserve-3d;
transform:translateZ(-100px);
}
}
El contenedor externo container
contiene un niño wrapper
. El niño es el 3d
elemento específico que se va a animar, por lo que debe establecer una propiedad transform-style: preserve-3d
.
Solo cuando se establece, el preserve-3d
elemento puede mostrar su 3d
efecto.
translateZ
Y translateX
, translateY
estos dos atributos no son lo mismo. translateX
Es a punto de moverse en el plano, translateY
se mueve en el plano vertical.
translateZ
Es un 3d
atributo No realiza desplazamientos hacia arriba, abajo, izquierda y derecha en el plano, sino que realiza desplazamientos dentro o fuera de la dirección perpendicular al plano.
translateZ(-100px)
Significa que el elemento se ha movido al interior de la pantalla 100px
. Según la regla de cerca, grande, lejano, pequeño, el efecto visual final del elemento se 100px
reduce en su conjunto. Si es positivo , se moverá a la fuera de la pantalla 100px
, y el efecto visual del elemento se agranda.
translateZ
preserve-3d
Aplicar solo en el elemento con el conjunto de atributos tendrá efecto, de modo que preserve-3d
todos los 3d
atributos puedan tener efecto.
block
Es 3d
el dom
elemento a transformar , por lo que necesita ser ambientado preserve-3d
y transform
transformado El elemento padre es container
equivalente a un escenario y block
puede ser considerado como un actor de la representación escénica.
perspective
Representa la distancia entre la audiencia y el escenario. Es concebible perspective
que cuanto menor sea el valor, más cerca estará la audiencia del escenario, y la escena en el escenario se verá con mayor claridad.
Correspondiente a la escena real, perspective
correspondiente a dom
la distancia entre los elementos en los ojos del usuario, cuanto mayor es la distancia, cuanto más lejos, wrapper
más pequeño y menos claro es el interior. Por el contrario, cuanto perspective
mayor es el mayor, wrapper
mayor es la apariencia y cuanto más claros sean los detalles internos.
perspective-origin
Puede entenderse como si el usuario está sentado en la posición izquierda, en la posición media o en la posición derecha del auditorio para ver la actuación en el escenario, y el efecto del campo visual es diferente.
Ahora volviendo al tema, continúe estudiando 3d
el diagrama de carrusel del efecto de volteo. Al disminuir el tiempo de animación, observe sus detalles, como se muestra en la siguiente figura:
Al observar la imagen de arriba, rápidamente me di cuenta de que los elementos que se van a animar no están disponibles en la página actual y deben ser js
generados dinámicamente por nosotros.
El elemento de animación es un cubo, que contiene dos efectos de movimiento. Uno es moverse hacia la izquierda y el otro es voltear hacia adelante. Es fácil moverse hacia la izquierda, configúrelo en un left
valor de cambio dinámico de posicionamiento absoluto . Y voltear puede RotateX(-90deg)
se puede hacer configurando Arrived (equivalente a X
invertir el 90
grado a lo largo del eje ).
El efecto de animación del cubo no es difícil de lograr, la dificultad radica en cómo generar dicho cubo.
Dibujar cubo
En la escena actual, el cubo solo necesita dibujar cuatro caras: superior, frontal, izquierda y derecha. La parte superior se almacena para que la siguiente imagen sea un carrusel, la parte delantera se almacena para la imagen que se muestra actualmente, y la izquierda y la derecha son negro. El fondo está relleno para hacer que la imagen sea más tridimensional, la html
estructura es la siguiente:
<div class="wrapper">
<div class="left"></div>
<div class="right"></div>
<div class="front"><img src="1.jpg"></div>
<div class="up"><img src="2.jpg"></div>
</div>
El left
, right
, front
y up
se establecen para el posicionamiento absoluto, anchura y altura están llenos con el elemento de matriz, left
y top
ajuste 0
.
front
Es la cara directamente al frente, originalmente se muestra en el plano y no es necesario realizar ningún procesamiento.
left
Para colocar el punto central en la esquina superior izquierda, el grado de y
renderizado a lo largo del eje 90
formará el lado.
.left {
transform-origin: 0% 0%;
transform: rotateY(90deg);
background-color: #333;
}
right
Debe mover todo el ancho hacia la derecha y luego girar a lo largo del eje y 90
para formar el lado derecho.
html += `
... //js中dom字符串拼接
<div class="right" style="transform: translateX(${unit_width}px) rotateY(90deg);">
...
</div>
...
`
up
La superficie primero establece el punto central en la esquina inferior izquierda, gira alrededor del X
eje 90
y luego se mueve hacia arriba en toda la altura para formar la parte superior.
.up{
transform-origin: 0% 100%;
}
html += `
... //js中dom字符串拼接
<div class="up" style="transform: rotateX(90deg) translateZ(${container_height}px);">
...
</div>
...
`
La dom
estructura de estas cuatro caras js
se empalma adentro y se coloca en el wrapper
padre correspondiente.Como se div
mencionó anteriormente , los atributos wrapper
deben establecerse adentro preserve-3d
, y los wrapper
elementos son los elementos que están realmente animados dom
.
wrapper
Después se encapsula el elemento, que se lanza en el elemento etapa container
, y los atributos y container
se fijan .3d
perspective
perspective-origin
Uno container
corresponde a una rebanada de cubo, y la html
cadena formada por todos los cubos cortados se coloca en el documento de la página y se renderiza, de esta manera dom
se generan los elementos animados .
Agregar animación de volteo
Los dom
elementos que realizan la animación han sido generados y renderizados en la página. Según el análisis anterior, agregar un atributo a cada cubo ( wrapper
correspondiente div
) rotateX(-90deg)
puede hacer que el cubo se voltee. Los resultados son los siguientes:
wrapper
Además, el rotateX(-90deg)
atributo se voltea hacia adelante, pero la posición final no está cerca del suelo.
La causa del accidente fue porque wrapper
era un cubo, no un plano simple, también contenía cuatro planos, ahora cuando se gira el cubo, la posición de su punto central es muy importante.
wrapper
La altura de está 100%
llena de todo el padre. A través de las pruebas, se encuentra que la transformación de atributo del cubo se basa en realidad en el frente ( front
cara). El punto central del cubo se encuentra en front
el medio de la front
altura de la cara. . Si la altura de la cara es 600px
, entonces Al 300px
dibujar un X
eje, gire todo el cubo a lo largo de este eje. Si la front
altura de la superficie es 800px
, entonces el cubo 400px
girará a lo largo del eje.
Ahora regrese al caso anterior, front
la altura de la cara está configurada para 100%
llenar el elemento principal, luego el cubo dibujará un eje en el medio y se volteará hacia adelante 90
, por lo que habrá un hueco debajo. No podemos dejar que el cubo girar y detenerse en el aire, para encontrar una manera de volver a ponerlo en el suelo.
De acuerdo con lo que dije antes, el cubo usa la front
superficie como superficie de referencia. Después de voltear el 90
grado, la front
superficie llega a la parte inferior. Luego, quieres que el cubo se mueva hacia abajo, porque está front
mirando hacia la parte inferior en este momento , y Solo es necesario configurarlo translateZ(contrainer_height/2)
para mover el cubo hacia abajo. La mitad de la altura está unida a la parte inferior.
Aunque esta configuración puede garantizar que el cubo volteado se adhiera a la parte inferior, la imagen de su interior se deforma.
Porque cuando el cubo está configurado rotateX(-90deg)
para girar hacia adelante, en realidad se mueve hacia adelante. De acuerdo con las reglas de casi grande y muy pequeño, el efecto visual de la imagen se agranda. Para resolver este problema, primero use el cubo translateZ(-contrainer_height/2)
para empujar la mitad de la altura en el interior y luego dejar que el cubo se voltee hacia adelante, para que se resuelva el problema del estiramiento de la imagen, el código es el siguiente:
while ((el = eles.shift())) {
//el对应着每个立方体的dom
//立方体先沿Z轴往后推一半高度,再朝前做翻转,翻转完后向下移动一半高度贴底
el.style.transform = `translateZ(${
-this.container_height / 2
}px) rotateX(-90deg) translateZ(${this.container_height / 2}px)`;
...
}
Una vez finalizado el efecto de volteo, encontraremos que el cubo está frente a nosotros y girando, no podemos ver el lado derecho del cubo con un fondo negro right
, por lo que parecerá muy adimensional.
Presenté un atributo antes perspective-origin:right center
. Esto es como la audiencia sentada en el lado derecho del auditorio, y el escenario es tan ancho como el auditorio, y hay una jaula de hierro en el escenario mirando hacia el frente de la audiencia. En este momento, el campo de visión de la audiencia solo puede ver En el frente de la jaula de hierro, si la jaula se empuja hacia el lado izquierdo del escenario, entonces el cliente sentado en el lado derecho de la audiencia no solo puede ver el frente de la jaula de hierro , pero también puede ver el lado derecho de la jaula de hierro.
De la misma manera, para que el cubo parezca más tridimensional cuando se voltea, el fondo negro de la derecha se puede mostrar durante la animación. Para lograr este propósito, es necesario mover el cubo a la izquierda. , además perspective-origin
del soporte de atributos, sale el cubo. El efecto tridimensional volteado sale.
Si desea que el cubo se mueva hacia la izquierda, solo necesita obtener los dom
elementos del cubo y left
asignarlos dinámicamente.