Dans un projet récent, je souhaite avoir un effet de collecte de points. Selon la description du patron, cet effet est similaire à l'effet de collecte d'énergie dans la forêt de fourmis d'Alipay. L'effet global est qu'il y a plusieurs éléments ponctuels flottant autour de l'arbre, glissant de haut en bas, comme des étoiles scintillantes. Après avoir cliqué pour les collecter, ils glissent le long du centre de l'arbre et disparaissent. L'énergie sur l'arbre augmente, et finalement s'étend. et devient un peu plus grand.
Tout d'abord, je pense que le contour de base est une terre, entourée de plusieurs étoiles scintillantes en demi-cercle, puis elles tombent sur la terre en même temps. Utilisez le positionnement CSS, border-radius pour dessiner un cercle, une animation, une action de clic pour déclencher une nouvelle animation et l'effet d'incrément de point est similaire à countUp.js, mais ce plug-in n'est pas utilisé ici et est implémenté manuellement.
(Partage de vidéos d'apprentissage : Tutoriel vidéo CSS)
1.1 Effet surround demi-cercle
Ceci Impliquant des connaissances mathématiques, le radian est obtenu en fonction de l'angle (radians = angle * pi / 180), puis converti en coordonnées, de sorte que les éléments intégraux entourent l'intégrale totale. Le code clé est le suivant :
this.integral.forEach(i => { // 角度转化为弧度 let angle = Math.PI / 180 * this.getRandomArbitrary(90, 270) // 根据弧度获取坐标 i.x = xAxis + 100 * Math.sin(angle) i.y = 100 + 100 * Math.cos(angle) // 贝塞尔函数 i.timing = this.timeFun[parseInt(this.getRandomArbitrary(0, 3))] })
Notez que la fonction de la fonction getRandomArbitrary() est d'obtenir des nombres aléatoires, comme suit :
// 求两个数之间的随机数 getRandomArbitrary(min, max) { return Math.random() * (max - min) + min; }
timeFunc est une collection de noms de fonctions Bessel, dans l'ordre pour obtenir l'effet de clignotement intégral (glissade de haut en bas), défini dans les données :
timeFun: ['ease', 'ease-in', 'ease-in-out', 'ease-out'], // 贝塞尔函数实现闪烁效果
1.2 Points de clignotement (glissade de haut en bas)
Utilisez l'animation CSS pour réaliser des points glissant de haut en bas, ici La façon dont on peut penser est transform: translateY(5px), qui consiste à se déplacer d'une certaine distance sur l'axe y et à lire l'animation en boucle. Le code est le suivant :
.foo { display: flex; font-size: 10px; align-items: center; justify-content: center; width: 30px; height: 30px; position: fixed; top: 0; left: 0; animation-name: slideDown; /*默认贝塞尔函数*/ animation-timing-function: ease-out; /*动画时间*/ animation-duration: 1500ms; /*动画循环播放*/ animation-iteration-count: infinite; -moz-box-shadow: -5px -5px 10px 3px rgb(277, 102, 63) inset; -webkit-box-shadow: -5px -5px 10px 3px rgb(277, 102, 63) inset; box-shadow: -5px -5px 10px 3px rgb(277, 102, 63) inset; } /*小积分上下闪烁*/ @keyframes slideDown { from { transform: translateY(0); } 50% { transform: translateY(5px); background-color: rgb(255, 234, 170); } to { transform: translateY(0); background: rgb(255, 202, 168); } }
Notez qu'en plus de déplacer les points de haut en bas, je laisse également la couleur d'arrière-plan changer en conséquence. Le rythme de déplacement de haut en bas ne peut pas être cohérent, sinon il semblera terne, utilisez donc une fonction de nombre aléatoire pour sélectionner au hasard l'une des fonctions de Bessel, de sorte que la boule d'intégration glisse de haut en bas et semble inégale. Le code clé est le suivant :
/*html*/{{item.value}}/*js*/ // data中定义 timeFun: ['ease', 'ease-in', 'ease-in-out', 'ease-out'], // 贝塞尔函数实现闪烁效果 // 随机获取贝塞尔函数 i.timing = this.timeFun[parseInt(this.getRandomArbitrary(0, 3))]
1.3 Effet croissant du total des points
Après avoir cliqué pour réclamer les points, le total des points doit être accumulé. Ceci est similaire à l'effet countUp.js, mais ce plug-in ne peut pas être cité ici pour cette fonction. Le projet utilise vue.js. Il est facile de penser à modifier les attributs réactifs des données pour changer les nombres. La clé est de savoir comment effectuer ce changement non pas d'un seul coup, mais progressivement. Mon idée ici est Promise+setTimeout, modifiant l'attribut data à certains intervalles, afin qu'il ne semble pas changer soudainement.
Afin de rendre l'effet d'animation fluide, divisez la durée totale (1 500 millisecondes) par le nombre de petites intégrales pour obtenir une valeur similaire à l'image clé de l'animation. Cette valeur est utilisée comme nombre de changements. , puis exécuté une fois à certains intervalles. Toutes les durées d'animation sont définies sur 1 500 millisecondes afin que l'effet global soit cohérent.
Le code clé est le suivant :
this.integralClass.fooClear = true this.totalClass.totalAdd = true this.totalText = `${this.totalIntegral}积分` let count = this.integral.length, timeoutID = null, tasks = [], totalTime = parseInt(1500 / count) const output = (i) => new Promise((resolve) => { timeoutID = setTimeout(() => { // 积分递增 this.totalIntegral += this.integral[i].value // 修改响应式属性 this.totalText = `${this.totalIntegral}积分` resolve(); }, totalTime * i); }) for (var i = 0; i < 5; i++) { tasks.push(output(i)); } Promise.all(tasks).then(() => { clearTimeout(timeoutID) })
1.4 Les petits points disparaissent, et l'effet d'expansion total des points
La dernière étape est que les petits points se déplacent dans la direction de l'intégrale totale et disparaissent, et l'intégrale totale se développe.
La petite intégrale se déplace et disparaît, la coordonnée de l'axe x se déplace vers la coordonnée de l'axe x de l'intégrale totale et l'axe y se déplace vers la coordonnée de l'axe y de l'intégrale totale. le point de coordonnées devient le même que l'intégrale totale, il semble donc que ce mouvement le long du centre soit le même. Lorsque les coordonnées de toutes les petites intégrales se déplacent ici, les données peuvent être supprimées. La clé CSS est la suivante :
.fooClear { animation-name: clearAway; animation-timing-function: ease-in-out; animation-iteration-count: 1; animation-fill-mode: forwards; -webkit-animation-duration: 1500ms; -moz-animation-duration: 1500ms; -o-animation-duration: 1500ms; animation-duration: 1500ms; } /*清除小的积分*/ @keyframes clearAway { to { top: 150px; left: 207px; opacity: 0; visibility: hidden; width: 0; height: 0; } }
Le total des points est étendu. Mon idée d'implémentation ici est transform: scale(1.5, 1.5); c'est-à-dire le rendre un peu plus grand que la taille d'origine, et enfin revenir. à la taille d'origine transform : scale(1 , 1);, la clé css est la suivante :
.totalAdd { animation-name: totalScale; animation-timing-function: ease-in-out; /*动画只播放一次*/ animation-iteration-count: 1; /*动画停留在最后一个关键帧*/ animation-fill-mode: forwards; -webkit-animation-duration: 1500ms; -moz-animation-duration: 1500ms; -o-animation-duration: 1500ms; animation-duration: 1500ms; } @keyframes totalScale { 50% { transform: scale(1.15, 1.15); -ms-transform: scale(1.15, 1.15); -moz-transform: scale(1.15, 1.15); -webkit-transform: scale(1.15, 1.15); -o-transform: scale(1.15, 1.15); } to { transform: scale(1, 1); -ms-transform: scale(1, 1); -moz-transform: scale(1, 1); -webkit-transform: scale(1, 1); -o-transform: scale(1, 1); } }
À ce stade, la logique de toute l'animation est clarifiée. Écrivons d'abord une démo que j'ai mise. le code sur github pour intégrer l'animation.
L'effet est le suivant :
Enfin dans le projet, une requête Ajax consiste à collecter des points. Il vous suffit de mettre l'animation dans le rappel de réussite de la requête ajax et vous avez terminé. Le code clé js est le suivant :
// 一键领取积分 aKeyReceive() { if (this.unreceivedIntegral.length === 0) { return bottomTip("暂无未领积分") } if (this.userInfo.memberAKeyGet) { let param = { memberId: this.userInfo.memberId, integralIds: this.unreceivedIntegral.map(u => u.id).join(","), integralValue: this.unreceivedIntegral.reduce((acc, curr, index, arr) => { return acc + curr.value }, 0) } this.$refs.resLoading.show(true) api.getAllChangeStatus(param).then(res => { let data = res.data if (data.success) { this.getRecordIntegralList() this.playIntegralAnim() } else { bottomTip(data.message) } }).finally(() => { this.$refs.resLoading.show(false) }) } else { this.$refs.refPopTip.show() } }, // 领取积分的动画 playIntegralAnim() { this.integralClass.fooClear = true this.totalClass.totalAdd = true this.totalText = `${this.statisticsData.useValue}积分` let count = this.unreceivedIntegral.length, timeoutID = null, tasks = [], totalTime = parseInt(1500 / count) const output = (i) => new Promise((resolve) => { timeoutID = setTimeout(() => { this.statisticsData.useValue += this.unreceivedIntegral[i].value this.totalText = `${this.statisticsData.useValue}积分` resolve(); }, totalTime * i); }) for (let i = 0; i < count; i++) { tasks.push(output(i)); } Promise.all(tasks).then(() => { clearTimeout(timeoutID) }) }
L'effet final une fois le projet en ligne est le suivant :
Notez que la raison pour laquelle la page clignote voici parce qu'il y a une requête ajax. L'état de chargement est en fait inutile si le serveur est totalement fiable.
Enfin, si vos lecteurs ont des besoins similaires, vous souhaiterez peut-être apprendre d'eux. Si vous avez de meilleures idées, veuillez me les apporter pour référence.
Pour plus de connaissances sur la programmation, veuillez visiter : Apprendre la programmation ! !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!