Quando eu estava navegando no CSSDesignAwards, encontrei um efeito que divide o conteúdo da imagem (site: https://weareludwig.com Você pode clicar nele para dar uma olhada. Foi muito legal, então tentei implementá-lo sozinho). e o efeito foi muito bom. Verifique o efeito https://codepen.io/geeknoble/pen/OQaOVG
analisarPrimeiro, podemos descobrir que o conteúdo da imagem é dividido em pequenos retângulos e cada retângulo é traduzido aleatoriamente. A função drawImage do Canvas pode cortar o conteúdo da imagem e desenhá-lo na tela do Canvas, portanto, o principal princípio de implementação desse efeito é usar drawImage. Existem dois efeitos principais, um é interromper e restaurar o conteúdo da imagem e o outro é mudar para a próxima imagem. DrawImage pode ser usado para ambos os efeitos, mas a distância do movimento é diferente. Depois de ter a ideia geral, você pode começar a implementá-la.
trabalho inicialPrimeiro precisamos inicializar algumas variáveis, como largura e altura da imagem, número de retângulos, tamanho do corte, etc., depois calcular as coordenadas de cada retângulo e usar um loop duplo para salvar as coordenadas do retângulo em dados. Cada retângulo tem um deslocamento aleatório, e esse deslocamento também precisa ser salvo aleatoriamente. Entre eles, x e y representam as coordenadas da tela, e x1 e y1 representam as coordenadas do recorte da imagem.
init: function (contexto, largura, altura, área, img) { this.context = context; this.img = img; this.imgWidth = img[0].width; 0 ].height; this.index = 0; //Número da imagem atual this.width = width; //Largura e altura da tela this.height = height; //O comprimento do pequeno retângulo this.countX = width / this.area; //O número de pequenos retângulos nas direções horizontal e vertical this.countY = height / this.area; .countX; //Largura e altura da imagem no retângulo pequeno this.wy = this.imgHeight / this.countY; //Status da imagem, true significa não dividir this.dataFlag = true; estado da coordenada, verdadeiro significa Nenhum valor aleatório this.duration é adicionado = 1000; //Tempo de animação this.duration2 = 1500; this.startTime = 0; this.data = []; //Informações de coordenadas do retângulo pequeno this.randoms = []; x1 = 0, y1 = 0, x = 0, y = 0; for (var i = 0; i < this.countY; i++) { for (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); this.data.push({ x1: x1, y1: y1, x: x, y: y }); //Adicionar valores aleatórios this.randoms.push(random(-this.area, this.area)); x1 += this.wx; wy; x = 0; y += esta.area } esta.checkMargin();Detectar bordas
Antes de adicionar um deslocamento ao retângulo, precisamos determinar se as coordenadas deslocadas excedem o limite da imagem. Por exemplo, se o retângulo no topo se mover no eixo y, ele só poderá se mover para cima. a coordenada atual mais o valor do deslocamento é menor que 0 ou maior que a largura e a altura da imagem. Se as coordenadas atualizadas forem menores que 0, o valor aleatório deve ser um número negativo. Você precisa alterar o valor aleatório para um número positivo. Se for maior que a altura da imagem, altere-o para um número negativo. Como cada retângulo se move em uma direção, escrevo aqui que os bits pares movem o eixo x e os bits ímpares movem o eixo y.
//Detectar borda checkMargin: function () { var self = this; this.data.forEach(function (item, index) { if (index % 2 == 0) { // Move o eixo x quando o índice é um múltiplo de 2 , caso contrário mova o eixo y if (item.x1 + self.randoms[index] < 0) // Mude para um número positivo self.randoms[index] = -self.randoms[index] if (item). .x1 + self.wx + self.randoms[index] > self.imgWidth ) // Muda para 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] if (item.y1 + self.randoms[índice] + self.wy > self.imgHeight) self.randoms[index] = -Math.abs(self.randoms[index]) } }) }separação e recuperação
A separação e restauração do conteúdo da animação consiste em atualizar o valor das coordenadas retangulares. Para interromper o conteúdo, basta adicionar valores aleatórios às coordenadas nos dados, e a restauração consiste em subtrair os valores aleatórios.
//Detectar borda checkMargin: function () { var self = this; this.data.forEach(function (item, index) { if (index % 2 == 0) { // Move o eixo x quando o índice é um múltiplo de 2 , caso contrário mova o eixo y if (item.x1 + self.randoms[index] < 0) // Mude para um número positivo self.randoms[index] = -self.randoms[index] if (item). .x1 + self.wx + self.randoms[index] > self.imgWidth ) // Muda para 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] if (item.y1 + self.randoms[índice] + self.wy > self.imgHeight) self.randoms[index] = -Math.abs(self.randoms[index]) } }) }
Depois de armazenar as coordenadas, você pode implementar a animação de tradução. O processo de movimento tem uma transição suave. Podemos usar o algoritmo de easing do Tween.js. tempo de animação. Para obter detalhes, consulte o artigo de Zhang Xinxu https://www.zhangxinxu.com/wordpress/2016/12/how-use-tween-js-animation-easing/. Tween.js pode ser usado para calcular a distância a ser movida em cada quadro e, em seguida, usar requestAnimationFrame para atualizar as coordenadas.
blockAnimation: function () { var flag = 1; if (this.state) { // Determine se deseja interromper a imagem ou restaurar a imagem this.update(true) } else { flag = -1; ; } var self = this; this.startTime = +new Date(); // Obtenha a hora atual this.state = !this.state; >= self.startTime + self.duration) { // Condição final da animação return false } self.data.forEach(function (item, index) { if (index % 2 == 0) { var pos = Math.tween.Expo. easyInOut(t - self.startTime, 0, self.randoms[index] * flag, self.duration); Calcule a distância movida em cada quadro 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); } }); requestAnimationFrame(animação })();
Neste ponto, a animação de separação e restauração foi implementada.
Troca de imagemA seguir, começamos a processar a parte de troca de imagem. É um pouco como a imagem do carrossel. A animação da imagem do carrossel move a posição de cada imagem pela largura da janela visual. altura para alcançar y Ligar o eixo. Diferente da imagem do carrossel, temos apenas uma tag de tela aqui. Ao alternar, precisamos apenas alterar as coordenadas da imagem atual e da próxima imagem. A distância móvel da imagem atual é y1 + pos, e a distância móvel de. a próxima imagem é y1 + pos - imgHeight (nem é preciso dizer por que imgHeight deve ser reduzido).
//Animação de deslizamento vertical verticalAnimation: function (val) { if (!this.time2) { return false } this.checkTime(2); Deslize para cima ou para baixo if ((this.index + val) < 0 || (this.index + val) >= (this.img.length)) { // Determine se o número de série da imagem é o final return false }; este.estado ?this.update(true): this.update(false); this.startTime = +new Date(); (função animação() { var t = +new Date(); if (t >= self.startTime + self .duration2) { val === 1 ? self.index++ : self.index--; //Ajustar a ordem das imagens 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 (função (item) { var pos = Math.tween.Cubic.easeInOut (t - self.startTime, 0, (self.imgHeight) * val, self.duration2); // Atualizar as coordenadas da imagem atual self.context.drawImage(self.img[self.index], item.x1, item.y1 + pos, self.wx, self.wy, item.x, item.y, self.area, self.area // Atualizar as coordenadas da próxima imagem self.context.drawImage(self.img[); self.índice + val], item.x1, item.y1 + pos - self.imgHeight * val, self.wx, self.wy, item.x, item.y, self.area, self.area); }); requestAnimationFrame(animação })() }
O mesmo vale para mudar o eixo x. Agora todas as funções estão quase concluídas. O código completo pode ser visualizado no codepen.
O texto acima é todo o conteúdo deste artigo. Espero que seja útil para o estudo de todos. Também espero que todos apoiem a Rede VeVb Wulin.