Maison  >  Article  >  interface Web  >  Comment créer une animation d'horloge à l'aide de Canvas

Comment créer une animation d'horloge à l'aide de Canvas

一个新手
一个新手original
2017-10-16 09:51:021657parcourir

En passant en revue les points de connaissances de Javascript à Canvas, j'ai vu un exemple d'horloge statique dessinée à l'aide de Canvas et j'ai voulu la transformer en une animation d'horloge qui affiche dynamiquement l'heure du système. De plus, couplé à une horloge à affichage numérique, un petit module horloge était né ! L'interface actuelle est encore relativement grossière, avec seulement une interface simple et des effets d'animation.

Cette horloge comprend deux parties, l'horloge à disque animé et l'horloge numérique. La première consiste à utiliser le délai d'attente pour appeler la méthode setTimeout() afin de créer un effet d'animation en boucle pour afficher l'heure. Examinons d'abord le code de l'horloge numérique. Il est relativement simple. L'horloge à disque est également conçue pour imiter l'horloge numérique.


var ntimeoutId = setTimeout(ntimeOut,0);function ntimeOut() {
    clearTimeout(ntimeoutId);    
    var now = new Date();    
    var hours = now.getHours().toString(),
        minutes = now.getMinutes().toString(),
        seconds = now.getSeconds().toString();    
        var time = hours+" : "+minutes+" : "+seconds;    
        var timep = document.getElementById("time");
    timep.innerHTML = time;
    ntimeoutId = setTimeout(ntimeOut, 1000);
}

  1. Tout d'abord, définissez un appel de délai d'attente pour appeler la méthode pour la première fois afin d'afficher l'heure actuelle du système. La raison pour laquelle l'heure est réglée. Il est 0 pour afficher l'heure sans délai.

2. Effacez l'appel de délai d'attente précédent avant chaque boucle (pourquoi devez-vous faire cela, je ne sais pas encore ??? Cela peut être lié aux performances de la mémoire, commenté Le programme peut être exécuté normalement à l'avenir.)

 3. Obtenez l'heure actuelle du système et enregistrez-la dans un certain format de chaîne.

 4. Afin de l'afficher dynamiquement sur la page, un élément p vide est défini dans la page Html pour stocker la chaîne temporelle. Utilisez la manipulation DOM pour l'ajouter à l'élément p afin de l'afficher dynamiquement.

5. En bouclant continuellement l'appel de délai d'attente, l'horloge numérique peut être affichée de manière dynamique et les changements dynamiques dans l'élément p peuvent également être vus via les outils de développement.

L'étape suivante consiste à créer une animation d'horloge de disque. La caractérisation du disque et de la valeur numérique est relativement simple. Méthode arc() et contexte Utilisez simplement la méthode .fillText(). Voici son code source :


     context.beginPath();
        context.restore();
        context.translate(0,0);
        context.clearRect(0,0,300,300);        //绘制时钟内外边框
        context.arc(150,150,149,0,2 * Math.PI,false);
        context.moveTo(295,150);
        context.arc(150,150,145,0,2 * Math.PI,false);

        context.font = "bold 18px Arial";
        context.textAlign = "center";        //绘制时钟表盘数值
        context.fillText("12",150,25);
        context.fillText("3",285,150);
        context.fillText("6",150,290);
        context.fillText("9",15,150);
        context.fillText("1",215,45);
        context.fillText("2",265,95);
        context.fillText("4",265,225);
        context.fillText("7",95,275);
        context.fillText("5",215,275);
        context.fillText("8",35,225);
        context.fillText("10",35,95);
        context.fillText("11",75,45);

        context.stroke();
        context.closePath();

 L'étape suivante consiste à dessiner le pointeur. Lorsque vous dessinez le pointeur, reportez-vous à. la méthode en élévation. , il sera beaucoup plus pratique d'utiliser la méthode d'opération de transformation context.translate() pour changer l'origine, puis dessiner le chemin comme pointeur. Une autre difficulté du dessin de pointeurs est le calcul des radians. Bien entendu, il s’agit d’un problème mathématique. Regardons d'abord le code source :


     //绘制指针        context.save();
        context.translate(150,150);        //时针
        context.moveTo(0,0);
        hour(hours);        function hour(thour) {
            context.save();            
            var newhour = 0;            
            if(thour>12) {
                newhour = thour-12;
            } else {
                newhour = thour;
            }
            context.rotate((2*Math.PI/12)*newhour);
            context.lineTo(0,-80);
            context.restore();
        }        //分针
        context.moveTo(0,0);
        minute(minutes);        function minute(tminute) {
            context.save();
            context.rotate((2*Math.PI/12)*tminute/5);
            context.lineTo(0,-110);
            context.restore();
        }        //秒针
        context.moveTo(0,0);
        second(seconds);        function second(tsecond) {
            context.save();
            context.fillStyle = "#fff";
            context.rotate((2*Math.PI/12)*tsecond/5);
            context.lineTo(0,-120);
            context.restore();
        }
        
        context.stroke();

Dans le dessin de pointeurs, chaque type de pointeur utilise une fonction pour modifier l'arc de chaque pointeur dessin. Pour obtenir l’effet d’animation de la rotation du pointeur. Pour l'aiguille des heures, convertissez l'horloge de vingt-quatre heures en horloge de douze heures et faites-la pivoter de 30° à chaque fois. L'aiguille des minutes et l'aiguille des secondes tournent de 0 à 11. Je crois que tout le monde est meilleur que moi pour les problèmes mathématiques simples. J'avais encore du mal pendant un moment. La méthode context.save() et la méthode context.restore() sont utilisées dans chaque fonction pour enregistrer et restaurer le chemin lors de l'initialisation, sinon le pointeur déraillera.

Tout le travail est pratiquement prêt. Il ne nous reste plus qu'à placer le cadran et les aiguilles de l'horloge dans l'appel de délai d'attente. Cependant, il reste encore certains problèmes qui nécessitent une attention particulière, comme le. Le cadran et les aiguilles de l'horloge sont différents, veillez donc à utiliser la sauvegarde et la restauration pour restaurer le chemin lors de l'initialisation, sinon le cadran et les aiguilles de l'horloge dérailleront. Une autre chose à noter est que lorsque vous utilisez Canvas pour créer des animations, chaque cycle d'animation doit effacer le canevas et le redessiner, sinon le pointeur continuera à tourner et se transformera en fleur.

Le code complet de l'horloge du disque est le suivant :


//显示指针时间var drawing = document.getElementById("drawing");if(drawing.getContext) {    
var context = drawing.getContext("2d");    
var rtimeoutId = setTimeout(roudClock,0);    
function roudClock() {
        clearTimeout(rtimeoutId);

        context.beginPath();
        context.restore();
        context.translate(0,0);
        context.clearRect(0,0,300,300);        //绘制时钟内外边框
                context.arc(150,150,149,0,2 * Math.PI,false);
        context.moveTo(295,150);
        context.arc(150,150,145,0,2 * Math.PI,false);

        context.font = "bold 18px Arial";
        context.textAlign = "center";        //绘制时钟表盘数值
                context.fillText("12",150,25);
        context.fillText("3",285,150);
        context.fillText("6",150,290);
        context.fillText("9",15,150);
        context.fillText("1",215,45);
        context.fillText("2",265,95);
        context.fillText("4",265,225);
        context.fillText("7",95,275);
        context.fillText("5",215,275);
        context.fillText("8",35,225);
        context.fillText("10",35,95);
        context.fillText("11",75,45);

        context.stroke();
        context.closePath();        
        var now = new Date();        
        var hours = now.getHours(),
            minutes = now.getMinutes(),
            seconds = now.getSeconds();        //绘制指针        
            context.save();
        context.translate(150,150);        //时针
                context.moveTo(0,0);
        hour(hours);        
        function hour(thour) {
            context.save();            
            var newhour = 0;            
            if(thour>12) {
                newhour = thour-12;
            } else {
                newhour = thour;
            }
            context.rotate((2*Math.PI/12)*newhour);
                        context.lineTo(0,-80);
            context.restore();
        }        //分针
           context.moveTo(0,0);
        minute(minutes);        
        function minute(tminute) {
            context.save();
            context.rotate((2*Math.PI/12)*tminute/5);
            context.lineTo(0,-110);
            context.restore();
        }        //秒针
                context.moveTo(0,0);
        second(seconds);        
        function second(tsecond) {
            context.save();
            context.fillStyle = "#fff";
            context.rotate((2*Math.PI/12)*tsecond/5);
            context.lineTo(0,-120);
            context.restore();
        }
        
        context.stroke();
        context.restore();
        context.translate(0,0);
        context.save();
        rtimeoutId = setTimeout(roudClock,1000);
    }    
}

Enfin, je résume ceci time Plusieurs problèmes rencontrés lors de la pratique de la démo :

1. Problème de redessinage du canevas

Lorsque l'animation du pointeur boucle, il n'y a aucun moyen d'effacer le chemin précédent, ce qui fait que chaque boucle laisse une marque. J'ai essayé d'utiliser la méthode clearRect() dans une petite plage, mais j'ai constaté qu'elle ne pouvait effacer que le contenu du cadran et des chiffres dans la plage, et que le pointeur laissait toujours des traces. Plus tard, grâce à la recherche, la réponse que j'ai obtenue est que lorsque vous utilisez Canvas pour créer des animations, vous devez le redessiner. Le contenu du canevas doit être effacé avant de dessiner un nouveau contenu, et chaque modification d'animation doit être effacée. Pour la méthode redraw, veuillez vous référer au lien. J'utilise la méthode clearRect() pour effacer l'intégralité du canevas.

2. Utilisation de la méthode save() et de la méthode restaurer()

Parce que les paramètres d'origine de mon cadran d'horloge et de mon pointeur sont différents, Par conséquent, après le redessinage, l'origine du cadran de l'horloge deviendra l'origine du pointeur, donc les méthodes save() et restaurer() doivent être utilisées pour la modifier. En plus de cet endroit, il existe également d'autres endroits qui doivent être utilisés. Il convient aux situations dans lesquelles les paramètres sont modifiés après l'opération, mais les paramètres d'origine doivent être utilisés pour les opérations ultérieures. Notez que ces deux méthodes enregistreront et restaureront uniquement les paramètres, pas le contenu.

3. Utilisation de la méthode Translate()

La méthode Translate() appartient à l'opération de transformation et peut changer l'origine du canevas . La valeur par défaut L'origine du canevas se trouve dans le coin supérieur gauche du canevas. L'utilisation de cette méthode facilite le tracé du chemin du pointeur. Bien sûr, il existe d'autres utilisations que je n'ai pas encore abordées.

4. Utilisation de la méthode setTimeout()

L'utilisation d'appels avec délai d'attente est une meilleure méthode que les appels intermittents. L'utilisation d'appels avec délai d'attente peut simuler des appels intermittents. . appel. Une boucle peut être joliment simulée en ajoutant un appel de délai d'attente dans la fonction dans laquelle l'appel de délai d'attente est transmis. Vous pouvez également limiter le nombre et la durée des boucles en fonction de certaines conditions de la fonction.

5. Correspondant à l'heure actuelle, comment utiliser les radians

C'est un problème mathématique avec lequel j'ai longtemps lutté. le temps, mais je ne me suis pas trompé. Après avoir fait demi-tour, ce n'est plus un problème technique pour comprendre le principe.

6. Concernant le problème de l'acquisition répétée et de la réutilisation des méthodes temporelles

Concernant la situation où il y a des codes répétés dans le code, je n'ai pas pensé à une meilleure façon de réduire la redondance. Par exemple, en termes de temps d'acquisition, il y a des définitions répétées dans les deux appels de timeout, mais s'ils sont placés globalement, il n'y aura aucun effet d'animation et seul le temps statique après la fin du chargement sera affiché. Une autre chose est qu'il y a des parties répétées dans le réglage de la fonction du pointeur. Peut-il être combiné en une seule méthode de fonction puis appelé ?

Tout le monde est invité à proposer des idées, à faire des suggestions sur les lacunes et à communiquer ensemble.

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn