Comme toujours, il suffit de regarder les photos !
L'effet est le suivant :
De grandes images HD !
Je travaille comme codeur depuis de nombreuses années, mais mes vieux yeux sont sombres et je ne vois pas clairement l'animation ? ! Alors regardez les captures d'écran statiques ! ! !
Les effets des différents scores sont les suivants :
Après avoir regardé l’émission du vendeur, jetons un coup d’œil au processus de production du produit !
Canvas dessine un cercle 1. En vue, le code dans <template lang=pug> est le suivant :
canvas#baseCanvas est l'anneau gris en bas
canvas#myCanvas est l'anneau coloré ci-dessus
Nous devons utiliser le style CSS pour nous aider à recouvrir l'anneau coloré au-dessus de l'anneau gris.
2. style CSS : 3. Code de dessin de style js-canvasCe code est également très simple, il suffit de regarder l'API du canevas
3-1. Dans le composant vue, définissez les variables requises en haut de la balise de script.
3-2. Dans l'objet méthode de vue, trois méthodes sont définies :
drawBaseCanvas : utilisé pour dessiner l'anneau gris inférieur. Puisque le cercle gris n’a aucun effet d’animation, dessinez simplement un cercle gris complet au début. drawClrCanvas : utilisé pour dessiner l'anneau coloré ci-dessus. clearCanvas : utilisé pour effacer le canevas. C’est ce qu’exige l’animation d’anneaux colorés. Parce que le cœur de notre effet d'animation en anneau est d'effacer l'anneau coloré de temps en temps, puis d'augmenter la valeur de l'angle final et de le redessiner, de sorte qu'il s'agisse d'une animation continue.
Voici le code des trois méthodes :
Les codes des trois méthodes ci-dessus sont presque tous des applications de l'API Canvas, il suffit de lire le didacticiel.
Uniquement dans la méthode draoClrCanvas, lors du dessin d'un cercle de canevas, la valeur de début et la valeur de fin sont définies dans le paramètre arc.
La valeur de départ détermine la position de départ du dessin du cercle, et la valeur de fin détermine la position de fin (il me semble avoir dit des bêtises, mais après avoir longuement réfléchi au texte de description de la pensée, je ne veux pas le supprimer hahaha)
Le calcul de cette valeur finale est pour moi assez compliqué.
Pourquoi la variable count doit-elle être calculée comme ça ? J'ai oublié comment je l'ai compris.
this.grade est un entier positif inférieur à 100, indiquant le score. Il est défini dans les données et la valeur par défaut est de 0 point.
Le cercle coloré est donc invisible au début car le point de départ et le point d’arrivée sont tous deux à 0 point.
Si vous modifiez la valeur de la note, de 0 à 100, la valeur de l'anneau de couleur de la toile changera également.
De cette façon, tant que nous modifions progressivement la valeur de la note et la redessinons, les anneaux colorés augmenteront progressivement pour obtenir l'effet d'animation.
Effet d'animation en anneauEn raison de mes besoins particuliers ici, l'animation doit être déclenchée à chaque fois que l'utilisateur se tourne vers le swiper où se trouve le canevas (plus tard, c'est plus gênant et nécessite que l'histogramme et les parties du canevas aient un effet d'entrée avant que l'animation ne démarre. L'effet est le plus long de l'image ci-dessus (comme cette animation gif).
Je dois donc utiliser swiper pour y parvenir. Dans la fonction de rappel du commutateur de balayage, le score de note est incrémenté continuellement à partir de 0 et le dessin de l'anneau coloré est redéclenché pour obtenir l'effet d'animation.
Le swiper que j'utilise dans vue est 'vue-awesome-swiper'. J'ai écrit les étapes de son utilisation dans d'autres articles.
Il y a un objet on dans la configuration de swiper dans vue-data. La fonction slideChange dans l'objet on est la fonction de rappel qui est déclenchée à chaque fois que le swiper tourne la page.
Ici, je vais parler de quelques points particuliers :
(1) vm : C'est une variable que j'ai stockée dans le script vue. Elle est initialisée à null, puis une fois montée, elle est affectée comme objet d'instance vue.
Initialisez les données et dessinez des cercles gris
Grâce à cette méthode, j'obtiens les valeurs des attributs grade et gradeTarget dans la fonction object-data-swiper-callback de l'instance vue et je les modifie.
ps : je ne sais pas si c'est une approche stupide. Quand j'ai fait ça, j'ai rencontré un problème, je ne savais pas comment obtenir l'instance de vue dans le rappel de swiper. Il y avait donc une manière si détournée de sauver le pays. Si j'ai une meilleure solution, j'espère que vous pourrez me proposer une nouvelle idée. Merci beaucoup, ma chère.
(2) (this.activeIndex == 2 && vm.isStar) || (this.activeIndex == 1 && !vm.isStar)
Ce jugement est porté pour des raisons commerciales et peut être ignoré.
cela pointe vers l'objet swiper dans la fonction swiperChange. this.activeIndex est une propriété de l'instance swiper. En termes officiels, il renvoie l'index du bloc actif actuel (bloc d'activation). Vous pouvez comprendre qu'il fait référence à la page vers laquelle vous vous tournez actuellement, qui est l'indice du swiper-slide que vous consultez actuellement.
En raison de mon identité en tant qu'utilisateur, je déciderai de manière décisive d'afficher ou non la page précédente du swiper où se trouve le canevas actuel. S'il n'est pas affiché, la page précédente ne sera pas dessinée du tout, alors l'indice swiper correspondant de la page actuelle deviendra (index-1).
Dans l'ensemble, lorsque les conditions sont remplies et que l'utilisateur se tourne vers la page swiper où se trouve le canevas, je déclencherai la logique de dessin en anneau dans le if. Sinon, allez à autre chose pour initialiser l'état de la page de données, effacez le minuteur pour mettre l'animation en pause et effacez l'anneau coloré.
(3)vm.aniShow
Comme mentionné dans mon dernier article « Dessiner des histogrammes avec Pure CSS », l'animation de l'histogramme doit être discutée en même temps que l'animation du canevas. Parce que leur implémentation d’animation doit coopérer avec la commutation des swiper. C'est le code ici :
Lorsque l'attribut vue - data - aniShow devient vrai, le nom de classe ani sera ajouté à div.row :
De même, si aniShow est vrai, la hauteur de progression sera attachée à sa propre valeur cible, c'est-à-dire que la hauteur réelle de progression sera attribuée à la hauteur de l'attribut de style après avoir été convertie en pourcentage.
À ce moment-là, étant donné que la transition de progression surveille le changement de hauteur, l’animation croissante de l’histogramme avec l’augmentation de la hauteur commence.
Sous le nom de classe ani, la transition-retard du progrès atteint son effet d'incrémentation très échelonné.
Il peut être déroutant de simplement lire la description textuelle, mais jetez un autre regard sur l'effet :
(4) Partie du code de dessin du cercle de couleur
gradeTarget est le score réel, qui est le résultat final à tirer.
La note commence à 0 et augmente jusqu'à la taille de gradeTarget.
Je n'ai pas directement ++vm.grade ici, et je ne sais pas à quoi je pensais à l'époque.
Si vous jugez, si la note augmente jusqu'à la valeur cible gradeTarget ou est supérieure à la valeur cible, arrêtez d'incrémenter et laissez grade=gradeTarget. Jugement qui appartient à la valeur critique. Dans la fonction de mouvement, cela est également considéré comme une détection de collision.
Au contraire, si l'objectif n'est pas atteint, la dernière toile dessinée sera effacée et un nouvel anneau coloré sera redessiné après une modification progressive de la note.
(5) Mettez tout cela dans setTimeout, faites une pause de 500 millisecondes avant l'exécution, afin d'attendre que le graphique à barres et le graphique en anneaux entrent sur le marché avant de commencer à dessiner l'effet incrémentiel du cercle.
En fait, le code ci-dessus est un processus logique très simple. Les lecteurs devraient être capables de le comprendre après avoir lu le code une fois.
Nouvelles idées :
J'ai réalisé cet effet il y a longtemps. Lorsque je réglais sur la méthode de production aujourd'hui, j'ai pensé à une solution d'optimisation pour mon propre code :
En fait, il n’est pas nécessaire de rappeler la méthode de dessin des cercles chromatiques dans le minuteur. Ce que nous avons directement modifié, c'est l'attribut this.grade. Il serait bon de surveiller les modifications de cet attribut. De cette façon, lorsque cette propriété est modifiée dans le timer, la méthode ring sera automatiquement exécutée.
C'est encore une idée et a encore besoin de ma pratique.
Effet incrémental du texte du milieu :Étant donné que la note est un score incrémentiel à chaque fois, vous pouvez utiliser la liaison de données bidirectionnelle de Vue pour lier directement la note en tant que valeur de score à la vue DOM correspondante.
Enfin, l'animation de l'anneau et du graphique à barres ci-dessus est combinée avec une animation pour contrôler le délai d'animation. Très simple.
Code source d'index.vue :
(Remarque, le code source a été légèrement organisé et extrait séparément. Par souci d'exhaustivité et pour protéger les autres codes commerciaux, certains noms de variables ont été modifiés, ce qui peut être légèrement différent des captures d'écran précédentes)
<template lang='pug'> .indexs#Indexs.app-bg transition(name=fade) swiper#swiperBox(:options=swiperOption ref=mySwiper) swiper-slide.swiper-slide1 .container .up swiper-slide.swiper -slide2(v-if=isShow) .mon-requin .up swiper-slide.swiper-slide3 .container .data-cont .data.data01 .data01-charts .row(v-for='item,index in Data' :key=index :class='aniShow ? ani:') . data-txt {{item.grade > 0 ? item.grade : 'Aucune donnée'}} .progress(:class='item.grade == 0 ? nodata : ' :style='hauteur : ' + (aniShow ? (item.grade >= 100 ? (100 * 1.5) / 100 : item.grade == 0 ? 0.04 : item.grade * 1.5 / 100 ) : 0) +'rem') span.pg-data .week {{item.week}} .data.data02 .data02-charts .canvas-box //- baseCanvas canvas#baseCanvas.my-canvas(ref=baseCanvas width=174 height=174) //- canvas canvas#myCanvas.my-canvas.clr-canvas(ref=myCanvas width =174 hauteur=174) .canvas-data #[span.num {{grade}}]points</template><script>var vm = null, timer1 = null, /* valeur de base du canevas*/ c = null, //document.getElementById(myCanvas); ctx = null, //canvas-2d canvas x = 161 / 2 + 1, //coordonnée du centre du cercle r = (161 - 10) / 2; //Taille du rayon/* composant swiper*/import { swiper, swiperSlide } depuis vue-awesome-swiper;import { getData } from ../io/getData;export default { name : Index, composants : { swiper, swiperSlide }, data() { return { grade : 0, //Note du score du graphique en beignetTarget : 78,54, //Numéro de score réel , vous pouvez modifier isShow : true après avoir demandé des données via ajax, // S'il faut afficher le deuxième swiper de page aniShow : false, // S'il faut activer l'animation du graphique à colonnes Données : [{ semaine : première semaine, note : 0 }, { semaine : deuxième semaine, note : 30 }, { semaine : troisième semaine, note : 99,99 }, { semaine : quatrième semaine, note : 76,98 }, { semaine : cinquième semaine, note : 100 }], swiperOption : { //paramètres du swiper notNextTick : true, direction : verticale, grabCursor : true, setWrapperSize : true, autoHeight : true, slidesPerView : 1, mousewheel : false, mousewheelControl : false, height : window.innerHeight, //Réglage de la hauteur, remplissage de la hauteur de l'appareil ResistanceRatio : 0, observeParents : true, initialSlide : 2 - 1, //Lors de la définition de l'initialisation , la page d'affichage par défaut du swiper, en partant de zéro : { slideChange() { if ( (this.activeIndex == 2 && vm.isShow) || (this.activeIndex == 1 && !vm.isShow) ) { console.log(this.activeIndex, vm.isShow, draw animation); setTimeout(function() { // Afficher l'animation de l'histogramme vm.aniShow = true; // Le minuteur déclenche en continu le dessin d'anneaux colorés pour obtenir l'effet d'animation d'anneau timer1 = setInterval(function() { // Modifier la rédaction de la partition intermédiaire var num = vm.grade; num++; if (num >= vm.gradeTarget) { vm.grade = vm.gradeTarget; clearInterval(timer1); } else { vm.grade = num; / 60); }, 500); } autre { // Après avoir tourné la page, initialisez l'état de la page de données, effacez le minuteur pour mettre l'animation en pause et effacez les anneaux colorés console.log (autres pages); clearInterval(timer1); ; vm.clearCanvas (); } } } }; calculé : {}, Mounted() { // Initialise les données, dessine un cercle gris vm = this ; this.$refs.myCanvas; ctx = c.getContext(2d); this.drawBaseCanvas(); }, méthodes : { drawBaseCanvas() { // dessin de toile/* valeur de base*/ var c = this.$refs.baseCanvas , //document.getElementById(myCanvas); // débogueur; ctx = c.getContext(2d), o = x, randius = r; /*Cercle gris par défaut*/ ctx.StrokeStyle = #eee; ctx.lineWidth = 10; ctx.beginPath(); ; }, clearCanvas() { // Effacer le canevas ctx.clearRect(0, 0, 200, 200 }, drawClrCanvas() { var gradient = ctx.createLinearGradient(75, 50, 5, 90); gradient.addColorStop(0, #C88EFF); gradient.addColorStop(1.0, #7E5CFF); Pour remplir ctx.lineWidth = 10; ctx.lineCap = round; ctx.shadowColor = rgba(191,142,255, 0,36); ctx.shadowBlur = 8; ctx.shadowOffsetY = 8; ctx.beginPath(); var count = this.grade / (100/2) + 1; x, r, Math.PI, Math.PI * nombre, faux); ctx.stroke(); } }};</script><style lang='scss'>// column chart.row { position : relative ; z-index : 1 ; largeur : 0,61rem ; - 0,08 - 0,38rem ; alignement du texte : centre ;}.data-txt { taille de la police : 0,2rem ; 0,2rem ; marge-bas : 0,09rem ;}.progress { hauteur : 0rem ; transition : hauteur 0,5 s facilité d'entrée-sortie ;}.ani { @for $i de 1 à 6 { &:nth-of-type( #{$i}) { .progress { délai de transition : #{$i * 0,15}s } } } // &:nth-of-type(1) { // .progress { // délai de transition : .4s ; // } // } // &:nth-of-type(2) { // .progress { // délai de transition : .8s // } // } // &:nth-of-type(3) { // .progress { // délai de transition : 1s; // } // } // &:nth-of-type(4) { / / .progrès { // délai de transition : 1,4 s ; // } // } // &:nth-of-type(5) { // .progress { // délai de transition : 1,8 s // } // }}.pg- données { affichage : largeur du bloc : 0,12rem ; hauteur : 100 % ; marge : 0 auto ; dégradé linéaire (0deg, #c88eff 0%, #7e5cff 100 % ); ombre de la boîte : 0 -0,04rem 0,14rem 0 rgba(129, 93, 255, 0,4) ; rayon de bordure : 0,05rem 0,05rem 0 0 ;}//0 points d'affichage règle.nodata { .pg- données { border-radius : 0 ; arrière-plan : #e7e7e7 ; box-shadow : aucun ; }}.week { taille de police : 0,2 rem ; hauteur de ligne : 0,2 rem ; marge supérieure : 0,08 rem ; couleur : #666 ;}// Graphique en anneaux - data02 data part.data02-charts { margin-top : 0,32rem; hauteur : 1,61rem;}.canvas-box { position : relative ; 1,61rem ; hauteur : 1,61rem ; marge-gauche : 0,92rem ;}.my-canvas { largeur : 1,61rem ; hauteur : 1,61rem ;}.clr-canvas { position : haut : 0 ; .canvas-data { position : absolue ; haut : 0,56rem gauche : 0 ; marge : auto ; -0,1rem ; alignement du texte : centre ; taille de la police : 0,24rem ;
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.