Cuando estaba navegando por CSSDesignAwards, encontré un efecto que divide el contenido de la imagen (sitio web: https://weareludwig.com. Puedes hacer clic en él para verlo). Me pareció genial, así que intenté implementarlo yo mismo. y el efecto fue bastante bueno. Comprueba el efecto https://codepen.io/geeknoble/pen/OQaOVG
analizarPrimero, podemos encontrar que el contenido de la imagen se divide en pequeños rectángulos y cada rectángulo se traduce aleatoriamente. La función drawImage de Canvas puede recortar el contenido de la imagen y dibujarlo en el lienzo de Canvas, por lo que el principio principal de implementación de este efecto es usar drawImage. Hay dos efectos principales, uno es interrumpir y restaurar el contenido de la imagen y el otro es cambiar a la siguiente imagen. DrawImage se puede usar para ambos efectos, pero la distancia de movimiento es diferente. Una vez que tengas la idea general, puedes empezar a implementarla.
trabajo inicialPrimero debemos inicializar algunas variables, como el ancho y alto de la imagen, el número de rectángulos, el tamaño del corte, etc., luego calcular las coordenadas de cada rectángulo y usar un bucle doble para guardar las coordenadas del rectángulo. en datos. Cada rectángulo tiene un desplazamiento aleatorio y este desplazamiento también debe guardarse en forma aleatoria. Entre ellos, xey representan las coordenadas del lienzo, y x1 e y1 representan las coordenadas del recorte de la imagen.
init: función (contexto, ancho, alto, área, img) { this.context = context; this.img = img; this.imgWidth = img[0].width // Ancho y alto de la imagen this.imgHeight = img[ 0 ].height; this.index = 0; //Número de imagen actual this.width = width; //Ancho y alto del lienzo this.height = height; //La longitud del rectángulo pequeño this.countX = ancho / this.area; //El número de rectángulos pequeños en las direcciones horizontal y vertical this.countY = height / this.area; .countX; // Ancho y alto de la imagen en el rectángulo pequeño this.wy = this.imgHeight / this.countY; this.state = true // Estado de la imagen, verdadero significa no dividido this.dataFlag = true; estado de coordenadas, verdadero significa que no se agrega ningún valor aleatorio a esta duración = 1000; // Tiempo de animación this.duration2 = 1500; this.startTime = 0; this.data = []; // Información de coordenadas del rectángulo pequeño this.randoms = []; x1 = 0, y1 = 0, x = 0, y = 0; para (var i = 0; i < this.countY; i++) { para (var j = 0; j < this.countX; j++) { context.drawImage(this.img[this.index], x1, y1, this.wx, this.wy, x, y, this.area, this.area //Almacenamiento de coordenadas rectangulares); this.data.push({ x1: x1, y1: y1, x: x, y: y }); //Agregar valores aleatorios this.randoms.push(random(-this.area, this.area)); x1 += this.wx; wy; x = 0; y += esta.area } this.checkMargin();Detectar bordes
Antes de agregar un desplazamiento al rectángulo, debemos determinar si las coordenadas desplazadas exceden el límite de la imagen. Por ejemplo, si el rectángulo en la parte superior se mueve en el eje y, solo puede moverse hacia arriba. la coordenada actual más el valor de desplazamiento es menor que 0 o mayor que el ancho y el alto de la imagen. Si las coordenadas actualizadas son menores que 0, entonces el valor aleatorio debe ser un número negativo. Debe cambiar el valor aleatorio a un número positivo. Si es mayor que la altura de la imagen, cámbielo a un número negativo. Dado que cada rectángulo se mueve en una dirección, escribo aquí que los bits pares mueven el eje x y los bits impares mueven el eje y.
//Detecta borde checkMargin: function () { var self = this;data.forEach(function (item, index) { if (index % 2 == 0) { // Mueve el eje x cuando el índice es a múltiplo de 2; de lo contrario, mueva el eje y if (item.x1 + self.randoms[index] < 0) // Cambiar a un número positivo self.randoms[index] = -self.randoms[index] if (item). .x1 + self.wx + self.randoms[index] > self.imgWidth ) // Cambiar a número negativo self.randoms[index] = -Math.abs(self.randoms[index]) } else { if (item.y1 + self randoms[índice] < 0) self.randoms[índice] = -self.randoms[índice] si (item.y1 + self.randoms[índice] + self.wy >. self.imgHeight) self.randoms[índice] = -Math.abs(self.randoms[índice]) } }) }separación y recuperación
La separación y restauración del contenido de la animación consiste en actualizar el valor de las coordenadas rectangulares. Para alterar el contenido, simplemente agregue valores aleatorios a las coordenadas en los datos, y la restauración consiste en restar los valores aleatorios.
//Detecta borde checkMargin: function () { var self = this;data.forEach(function (item, index) { if (index % 2 == 0) { // Mueve el eje x cuando el índice es a múltiplo de 2; de lo contrario, mueva el eje y if (item.x1 + self.randoms[index] < 0) // Cambiar a un número positivo self.randoms[index] = -self.randoms[index] if (item). .x1 + self.wx + self.randoms[index] > self.imgWidth ) // Cambiar a número negativo self.randoms[index] = -Math.abs(self.randoms[index]) } else { if (item.y1 + self randoms[índice] < 0) self.randoms[índice] = -self.randoms[índice] si (item.y1 + self.randoms[índice] + self.wy >. self.imgHeight) self.randoms[índice] = -Math.abs(self.randoms[índice]) } }) }
Después de almacenar las coordenadas, puede implementar la animación de traducción. El proceso de movimiento tiene una transición suave. Podemos usar el algoritmo de aceleración de Tween.js. Este algoritmo tiene 4 parámetros: la hora actual, la posición inicial y la posición final. tiempo de animación. Para obtener más información, consulte el artículo de Zhang Xinxu https://www.zhangxinxu.com/wordpress/2016/12/how-use-tween-js-animation-easing/. Tween.js se puede usar para calcular la distancia a moverse en cada cuadro y luego usar requestAnimationFrame para actualizar las coordenadas.
blockAnimation: function () { var flag = 1; if (this.state) { // Determinar si interrumpir la imagen o restaurarla this.update(true) } else { flag = -1; ; } var self = this; this.startTime = +new Date(); // Obtener la hora actual this.state = !this.state; (función animación() { var t = +new Date(); if (t >= self.startTime + self.duration) { // Condición final de la animación return false } self.data.forEach(function (item, index) { if (index % 2 == 0) { var pos = Math.tween.Expo. facilidadInOut(t - self.startTime, 0, self.randoms[index] * flag, self.duration); Calcula la distancia movida en cada cuadro self.context.drawImage(self.img[self.index], item.x1 + pos, item.y1, self.wx, self.wy, item.x, item.y, self. área, self.area); } else { var pos = Math.tween.Expo.easeInOut(t - self.startTime, 0, self.randoms[index] * flag, self.duration); self.context.drawImage(self.img[self.index], item.x1, item.y1 + pos, self.wx, self.wy, item.x, item.y, self.area, self.area); } }); solicitarAnimationFrame(animación);
En este punto se ha implementado la animación de separación y restauración.
Cambio de imagenA continuación, comenzamos a procesar la parte de cambio de imagen. Esto es un poco como la imagen del carrusel. La animación de la imagen del carrusel mueve la posición de cada imagen según el ancho de la ventana visual. Lo mismo ocurre aquí. altura a alcanzar y Conmutación en el eje. A diferencia de la imagen del carrusel, aquí solo tenemos una etiqueta de lienzo. Al cambiar, solo necesitamos cambiar las coordenadas de la imagen actual y la siguiente. La distancia de movimiento de la imagen actual es y1 + pos, y la distancia de movimiento de. la siguiente imagen es y1 + pos. - imgHeight (no hace falta decir por qué se debe reducir imgHeight).
// Animación de deslizamiento vertical verticalAnimation: function (val) { if (!this.time2) { return false } this.checkTime(2); Deslice hacia arriba o hacia abajo if ((this.index + val) < 0 || (this.index + val) >= (this.img.length)) { // Determina si el número de serie de la imagen es el final return false } este.estado ? this.update(true) : this.update(false); this.startTime = +nueva fecha(); (función animación() { var t = +nueva fecha(); if (t >= self.startTime + self .duration2) { val === 1 ? self.index++ : self.index--; //Ajustar el orden de las imágenes self.index < 0 ? self.index = self.img.length - 1 : self.index; .índice >= self.img.length? self.index = 0: self.index; return false; } self.data.forEach(función (elemento) { var pos = Math.tween.Cubic.easeInOut(t - self.startTime, 0, (self.imgHeight) * val, self.duration2); // Actualiza las coordenadas de la imagen actual self.context.drawImage(self.img[self.index], item.x1, item.y1 + pos, self.wx, self.wy, item.x, item.y, self.area, self.area // Actualiza las coordenadas de la siguiente imagen self.context.drawImage(self.img); self.index + val], item.x1, item.y1 + pos - self.imgHeight * val, self.wx, self.wy, item.x, item.y, self.area, self.area); }); solicitarAnimationFrame(animación);
Lo mismo ocurre con el cambio del eje x. Ahora todas las funciones están casi completas. El código completo se puede ver en el codepen.
Lo anterior es el contenido completo de este artículo. Espero que sea útil para el estudio de todos. También espero que todos apoyen VeVb Wulin Network.