Lorsque je parcourais CSSDesignAwards, j'ai trouvé un effet qui divise le contenu de l'image (site Web : https://weareludwig.com Vous pouvez cliquer dessus pour y jeter un œil, c'était très cool, alors j'ai essayé de l'implémenter moi-même, et l'effet était plutôt bon. Vérifiez l'effet https://codepen.io/geeknoble/pen/OQaOVG
analyserPremièrement, nous pouvons constater que le contenu de l’image est divisé en petits rectangles, et chaque rectangle est traduit de manière aléatoire. La fonction drawImage de Canvas peut recadrer le contenu de l'image et le dessiner dans le canevas Canvas, donc le principal principe de mise en œuvre de cet effet est d'utiliser drawImage. Il existe deux effets principaux, l'un consiste à perturber et à restaurer le contenu de l'image, et l'autre à passer à l'image suivante. DrawImage peut être utilisé pour les deux effets, mais la distance de déplacement est différente. Une fois que vous avez l’idée générale, vous pouvez commencer à la mettre en œuvre.
travail initialNous devons d'abord initialiser certaines variables, telles que la largeur et la hauteur de l'image, le nombre de rectangles, la taille de découpe, etc., puis calculer les coordonnées de chaque rectangle et utiliser une double boucle pour enregistrer les coordonnées du rectangle dans les données. . Chaque rectangle a un déplacement aléatoire. Ce déplacement doit également être enregistré et stocké de manière aléatoire. Parmi eux, x et y représentent les coordonnées du canevas, et x1 et y1 représentent les coordonnées du recadrage de l'image.
init: function (contexte, largeur, hauteur, zone, img) { this.context = context; this.img = img; this.imgWidth = img[0].width; //Largeur et hauteur de l'image this.imgHeight = img[ 0 ].height; this.index = 0; //Numéro de l'image actuelle this.width = width; //Largeur et hauteur du canevas this.height = height; //La longueur du petit rectangle this.countX = width / this.area; //Le nombre de petits rectangles dans les directions horizontale et verticale this.countY = height / this.area; .countX; //Largeur et hauteur de l'image dans le petit rectangle this.wy = this.imgHeight / this.countY; this.state = true; //Statut de l'image, true signifie qu'elle n'est pas divisée this.dataFlag = true //Petit rectangle; état de coordonnées, vrai signifie qu'aucune valeur aléatoire cette durée n'est ajoutée = 1000; //Durée d'animation this.duration2 = 1500; this.startTime = 0; this.data = []; //Informations sur les coordonnées du petit rectangle this.randoms = []; x1 = 0, y1 = 0, x = 0, y = 0; pour (var je = 0; je < this.countY; i++) { pour (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 //Coordonnées rectangulaires de stockage); this.data.push({ x1 : x1, y1 : y1, x : x, y : y }); //Ajouter des valeurs aléatoires this.randoms.push(random(-this.area, this.area)); x1 += this.wx; x += this.area } x1 = 0; wy; x = 0; y += this.area; } this.checkMargin();Détecter les bords
Avant d'ajouter un déplacement au rectangle, nous devons déterminer si les coordonnées déplacées dépassent la limite de l'image. Par exemple, si le rectangle en haut se déplace sur l'axe y, il ne peut se déplacer que vers le haut. la coordonnée actuelle plus la valeur de déplacement est inférieure à 0 ou supérieure à la largeur et à la hauteur de l'image. Si les coordonnées mises à jour sont inférieures à 0, alors la valeur aléatoire doit être un nombre négatif. Vous devez remplacer la valeur aléatoire par un nombre positif. Si elle est supérieure à la hauteur de l'image, remplacez-la par un nombre négatif. Puisque chaque rectangle se déplace dans une direction, j’écris ici que les bits pairs déplacent l’axe des x et les bits impairs déplacent l’axe des y.
//Détecter le bord checkMargin : function () { var self = this; this.data.forEach(function (item, index) { if (index % 2 == 0) { // Déplacer l'axe des x lorsque l'index est un multiple de 2 , sinon déplacez l'axe y if (item.x1 + self.randoms[index] < 0) // Passage à un nombre positif self.randoms[index] = -self.randoms[index] if (item .x1 + self.wx + self.randoms[index] > self.imgWidth ) // Changement en nombre négatif self.randoms[index] = -Math.abs(self.randoms[index]) } else { if (item.y1 + self . randoms[index] < 0) self.randoms[index] = -self.randoms[index]; if (item.y1 + self.randoms[index] + self.wy > self.imgHeight) self.randoms[index] = -Math.abs(self.randoms[index]) } }) }séparation et récupération
La séparation et la restauration du contenu de l'animation consistent à mettre à jour la valeur des coordonnées rectangulaires. Pour perturber le contenu, il suffit d'ajouter des valeurs aléatoires aux coordonnées dans les données, et la restauration consiste à soustraire les valeurs aléatoires.
//Détecter le bord checkMargin : function () { var self = this; this.data.forEach(function (item, index) { if (index % 2 == 0) { // Déplacer l'axe des x lorsque l'index est un multiple de 2 , sinon déplacez l'axe y if (item.x1 + self.randoms[index] < 0) // Passage à un nombre positif self.randoms[index] = -self.randoms[index] if (item .x1 + self.wx + self.randoms[index] > self.imgWidth ) // Changement en nombre négatif self.randoms[index] = -Math.abs(self.randoms[index]) } else { if (item.y1 + self . randoms[index] < 0) self.randoms[index] = -self.randoms[index]; if (item.y1 + self.randoms[index] + self.wy > self.imgHeight) self.randoms[index] = -Math.abs(self.randoms[index]) } }) }
Après avoir stocké les coordonnées, vous pouvez implémenter l'animation de traduction. Le processus de mouvement a une transition en douceur. Nous pouvons utiliser l'algorithme d'accélération de Tween.js. Cet algorithme a 4 paramètres : l'heure actuelle, la position initiale et la position finale. temps d'animation. Pour plus de détails, veuillez consulter l'article de Zhang Xinxu https://www.zhangxinxu.com/wordpress/2016/12/how-use-tween-js-animation-easing/. Tween.js peut être utilisé pour calculer la distance à parcourir dans chaque image, puis utiliser requestAnimationFrame pour mettre à jour les coordonnées.
blockAnimation: function () { var flag = 1; if (this.state) { // Détermine s'il faut perturber l'image ou restaurer l'image this.update(true) } else { flag = -1; ; } var self = this; this.startTime = +new Date(); // Récupère l'heure actuelle this.state = !this.state; (function animation() { var t = +new Date(); if (t >= self.startTime + self.duration) { // Condition de fin d'animation 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); Calculez la distance parcourue dans chaque image self.context.drawImage(self.img[self.index], item.x1 + pos, item.y1, self.wx, self.wy, item.x, item.y, self. zone, 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(animation); })( }
A ce stade, l'animation de séparation et de restauration a été mise en œuvre.
Changement d'imageEnsuite, nous commençons à traiter la partie de changement d'image. C'est un peu comme l'image du carrousel. L'animation de l'image du carrousel déplace la position de chaque image de la largeur de la fenêtre visuelle. La même chose est vraie ici. hauteur à atteindre y Mise en marche de l'axe. Contrairement à l'image du carrousel, nous n'avons ici qu'une seule balise de toile. Lors du changement, il nous suffit de modifier les coordonnées de l'image actuelle et de l'image suivante. La distance de déplacement de l'image actuelle est y1 + pos, et la distance de déplacement de. l'image suivante est y1 + pos. - imgHeight (il va sans dire pourquoi imgHeight devrait être réduit).
//Animation coulissante verticale verticalAnimation : function (val) { if (!this.time2) { return false; } this.checkTime(2); Faites glisser vers le haut ou vers le bas if ((this.index + val) < 0 || (this.index + val) >= (this.img.length)) { // Déterminez si le numéro de série de l'image est la fin return false } cet.état ? this.update(true) : this.update(false); this.startTime = +new Date(); (function animation() { var t = +new Date(); if (t >= self.startTime + self .duration2) { val === 1 ? self.index++ : self.index--; //Ajuster l'ordre des images self.index < 0 ? .index >= self.img.length ? self.index = 0 : self.index; return false; } self.data.forEach(function (élément) { var pos = Math.tween.Cubic.easeInOut(t - self.startTime, 0, (self.imgHeight) * val, self.duration2); // Mettre à jour les coordonnées de l'image actuelle self.context.drawImage(self.img[self.index], item.x1, item.y1 + pos, self.wx, self.wy, item.x, item.y, self.area, self.area // Mettre à jour les coordonnées de l'image suivante 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); }); requêteAnimationFrame(animation); })() }
Il en va de même pour le changement de l'axe X. Désormais, toutes les fonctions sont presque terminées. Le code complet peut être visualisé dans le codepen.
Ce qui précède représente l’intégralité du contenu de cet article. J’espère qu’il sera utile à l’étude de chacun. J’espère également que tout le monde soutiendra le réseau VeVb Wulin.