IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Optimisation d'une animation dans canvas de html5


Sujet :

JavaScript

  1. #1
    Membre chevronné
    Avatar de Archimède
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2005
    Messages
    1 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 1 644
    Points : 1 975
    Points
    1 975
    Par défaut Optimisation d'une animation dans canvas de html5
    Bonjour, ayant plutôt l'habitude de réaliser mes animations en actionscript, je cherchais à comparer les deux technologies d'un point de vue fluidité et facilité de conception.
    Je me suis focalisé sur une animation simple de dessin avec translation et rotation. une roue en déplacement avec un repère qui tourne à l'intérieur.

    ci-joint mes deux tentatives de réalisation en javascript/html5

    une sans utilisation de translate() rotate() et l'autre avec...
    ci-joint :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
     
    <!DOCTYPE html>
    <!--
    To change this license header, choose License Headers in Project Properties.
    To change this template file, choose Tools | Templates
    and open the template in the editor.
    -->
    <html>
        <head>
            <title>Roue javascript</title>
            <meta charset="UTF-8">   
        </head>
        <body>
            <canvas id="canvas" width="1024" height="600">
                <p> votre navigateur ne supporte pas Canvas. Mettez-le à jour</p>
            </canvas>
            <script type="text/javascript">
                var canvas = document.querySelector('#canvas');
                var context = canvas.getContext('2d');
                var theta = 0;  //angle de rotation en radian
                var oldtheta = 0;//angle de rotation correspondant à la frame précédente
                var R = 100;  //rayon de la roue
                var retour = new Boolean(false);
                var penw = 3;
                var pi=Math.PI;
     
                function draw()
                {
                    context.save();
                    context.strokeStyle = "black";
                    context.lineWidth = penw;
     
     
                    context.clearRect(R * oldtheta-penw, 10-penw, 2 * R+2*penw, 2 * R+2*penw); //obturation (on efface l'image précédente à chaque fois en tenant compte du pen width)
                    //dessin du contour de la roue
                    context.beginPath();
                    context.arc(R * theta+R, R + 10, R, 0, 2*pi);
                    context.stroke();
     
                    //dessin des quatre rayons
                    for (var i = 0; i <= 3; i++)
                    {
                        context.beginPath();
                        context.moveTo(R * (1+theta), R + 10);
                        context.lineTo(R * (1+theta+ Math.cos(theta + i * pi/2)), 10 + R * (1 + Math.sin(theta + i * pi/2)));
                        context.stroke();
                    }
     
                    //dessin du sol
     
                    context.beginPath();
                    context.moveTo(0, 2 * R + 13);
                    context.lineTo(canvas.width, 2 * R + 10+penw);
                    context.stroke();
     
                    if ((R * theta > canvas.width - 2*R) || (theta < 0)) {
                        retour = !retour;
                    }
                }
     
                function render()
                {
                    draw();
                    window.requestAnimationFrame(render);
                    oldtheta = theta;
                    if (retour) {
                        theta += Math.PI / 180;
                    } else {
                        theta -= Math.PI / 180;
                    }
     
                }
     
                render();
     
                window.requestAnimFrame =
                        window.requestAnimationFrame || // La fonction standard
                        window.webkitRequestAnimationFrame || // Chrome et Safari.
                        window.mozRequestAnimationFrame || //  Firefox.
                        window.ORequestAnimationFrame || //  Opera.
                        window.msRequestAnimationFrame; // Internet Explorer. 
            </script>
        </body>
    </html>
    la seconde :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
     
    <!DOCTYPE html>
     
    <html>
        <head>
            <title>roue en javascript</title>
            <meta charset="UTF-8">
     
        </head>
        <body>
            <canvas id="canvas" width="1024" height="600">
                <p> votre navigateur ne supporte pas Canvas. Mettez-le à jour</p>
            </canvas>
            <script type="text/javascript">
                var canvas = document.querySelector('#canvas');
                var context = canvas.getContext('2d');
                var theta = 0;  //angle de rotation en radian
                var R = 100;  //rayon de la roue
                var retour = new Boolean(false);
                var penw = 3;
     
                function draw()
                {
                    context.save();
                      //obturation (on efface la frame précédente=> peu efficace ici-ça plombe l'animation)
                    context.clearRect(0, 0, canvas.width, canvas.height);
     
     
                    context.translate(R * theta + R, R + 10);//déplacement de l'origine du canvas au centre de la roue
                    context.rotate(theta);//rotation des axes du canvas
     
     
     
                    context.strokeStyle = "black";
                    context.lineWidth = penw;
                    //dessin du contour de la roue
                    context.beginPath();
                    context.arc(0, 0, R, 0, 2 * Math.PI);
                    context.stroke();
     
                    //dessin des quatre rayons
                    for (var i = 0; i <= 3; i++)
                    {
                        context.beginPath();
                        context.moveTo(0, 0);
                        context.lineTo(R * Math.cos(i * Math.PI / 2), R * Math.sin(i * Math.PI / 2));
                        context.stroke();
                    }
     
     
                    context.restore();//retour de l'origine du contexte graphique sur (0,0) en supprimant la rotation
                    //dessin du sol
                    context.beginPath();
                    context.moveTo(0, 2 * R + 10 + penw);
                    context.lineTo(canvas.width, 2 * R + 10 + penw);
                    context.stroke();
                    //gestion de l'aller et retour
                    if ((R * theta >= canvas.width - 2 * R) || (theta < 0)) {
                        retour = !retour;
                    }
                }
     
                function render()
                {
                    draw();
                    window.requestAnimationFrame(render);
     
                    if (retour) {
                        theta += Math.PI / 180;
                    } else {
                        theta -= Math.PI / 180;
                    }
     
                }
     
                render();
     
                window.requestAnimFrame =
                        window.requestAnimationFrame || // La fonction standard
                        window.webkitRequestAnimationFrame || // Chrome et Safari.
                        window.mozRequestAnimationFrame || //  Firefox.
                        window.ORequestAnimationFrame || //  Opera.
                        window.msRequestAnimationFrame; // Internet Explorer. 
            </script>
        </body>
    </html>
    Ma question est : quelle est la meilleure méthode à adopter... faut-il privilégier la seconde méthode (translate() rotate() du canvas) plutôt que la première ?
    Sachant qu'il faudrait que j'obture uniquement sur le dessin de la précédente frame dont le canvas a subi une rotation...

    Des idées d'optimisation puisque je débute presque dans ce langage et que je ne suis pas convaincu de l'intérêt de migrer vers html5/javascript hormis les plantages de flashplayer et la désaffection de flash par les distributeurs de pub.

  2. #2
    Membre confirmé

    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    311
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 311
    Points : 545
    Points
    545
    Par défaut
    Je te conseille la 2eme méthode, auquel j’aurai poussé le vice jusqu’à utiliser un context.rotate dans la boucle des rayons !

    Le context 2D peut utiliser l’accélération matérielle donc il est préférable de réduire tes calcules trigos du javascript en utilisant les méthode de changement de repère matriciel ( scale , rotate, translate et transform). De manière plus générale, quel que soit le langage ou la techno, il est préférable de rechercher une solution géométrique, plutôt qu’arithmétique, si tes équations sont lineaire ----> utilisation direct des calcules matriciel !

    Concernant ton obturation partielle, je suis pas convaincu que cela soit plus rapide, surtout si ta scène devient plus Complexe !

    Apres si tu recherches la performance ultime, je te conseille d’utiliser les contextes WebGL et WebGL2
    ShaderElement : Bénéficier de l’accélération graphique simplement par une nouvelle balise HTML <shader>
    ODE.js : portage JavaScript du célèbre moteur physique 3D Open Dynamics Engine

  3. #3
    Membre chevronné
    Avatar de Archimède
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2005
    Messages
    1 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 1 644
    Points : 1 975
    Points
    1 975
    Par défaut
    Je te conseille la 2eme méthode, auquel j’aurai poussé le vice jusqu’à utiliser un context.rotate dans la boucle des rayons !

    Le context 2D peut utiliser l’accélération matérielle donc il est préférable de réduire tes calcules trigos du javascript en utilisant les méthode de changement de repère matriciel ( scale , rotate, translate et transform). De manière plus générale, quel que soit le langage ou la techno, il est préférable de rechercher une solution géométrique, plutôt qu’arithmétique, si tes équations sont lineaire ----> utilisation direct des calcules matriciel !
    En effet, c'est ce que je pensais en ayant envisagé de reprendre ma première mouture...Cependant la première méthode donne un résultat nettement plus fluide.

    Concernant ton obturation partielle, je suis pas convaincu que cela soit plus rapide, surtout si ta scène devient plus Complexe !
    La taille du clearRect a pourtant une importance non négligeable... Il suffit de mettre : canvas.height/2 pour gagner déjà en fluidité.
    Ce qui fait la différence avec la seconde mouture au niveau de la fluidité, c'est que j'obture uniquement sur la surface de dessin de la frame précédente.

    Apres si tu recherches la performance ultime, je te conseille d’utiliser les contextes WebGL et WebGL2
    Merci pour l'info... Sinon j'ai vu KineticJS qui n'a pas l'air mal ! et qui travaille avec une méthode qui ressemble à celle de flash dans la façon de coder...
    Je ne sais pas si tu connais ? je n'ai pas encore testé...

    merci pour ta réponse.

  4. #4
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 957
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 957
    Points : 44 121
    Points
    44 121
    Par défaut
    Bonjour,
    je constate que tu fais pas mal de calcul trigo, une méthode est de pré-calculer et d'enregistrer dans une table les valeurs, on tourne en rond c'est le cas de le dire.

    Je rejoins p3ga5e dans le sens où tu pourrais tout également créer ta roue, la récupérer sous forme d'image et n'appliquer la rotation qu'à celle ci via un rotate.

  5. #5
    Membre chevronné
    Avatar de Archimède
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2005
    Messages
    1 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 1 644
    Points : 1 975
    Points
    1 975
    Par défaut
    Merci pour les remarques . Je regarde tout ça...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Une animation dans des DIV
    Par edophie dans le forum ActionScript 1 & ActionScript 2
    Réponses: 2
    Dernier message: 30/08/2007, 20h46
  2. Optimisation d'une insertion dans une BD Oracle
    Par Hamma_TUN dans le forum Oracle
    Réponses: 5
    Dernier message: 13/07/2006, 10h55
  3. [Stratégie] Afficher une animation dans un JScrollPane
    Par patmaba dans le forum AWT/Swing
    Réponses: 8
    Dernier message: 11/10/2005, 09h49
  4. Réponses: 6
    Dernier message: 14/12/2004, 02h47
  5. Réponses: 4
    Dernier message: 18/04/2004, 13h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo