CONNAISSEZ-VOUS D'AUTRES BONNES PRATIQUES POUR LES CANEVAS ?
Veuillez ajouter à ce fil de discussion ce que vous savez, ce que vous avez appris ou ce que vous avez lu en ligne sur les meilleures pratiques, les trucs et astuces pour les performances de Canvas.
Canvas étant encore très récent sur Internet, et ne présentant aucun signe de vieillissement à ce que je vois dans le futur, il n'y a pas beaucoup de "meilleures pratiques" documentées ou d'autres conseils vraiment importants à connaître absolument pour développer avec Canvas à un endroit particulier. Les choses de ce genre sont éparpillées un peu partout et souvent sur des sites moins connus.
Il y a tellement de choses que les gens doivent savoir, et encore tellement de choses à apprendre aussi.
J'ai voulu partager quelques éléments pour aider les personnes qui apprennent à utiliser Canvas et peut-être même celles qui le connaissent déjà bien. J'espère obtenir des réactions de la part d'autres personnes sur ce qu'elles considèrent comme les meilleures pratiques ou d'autres trucs et astuces pour travailler avec Canvas en HTML5.
Je voudrais commencer par une chose que j'ai personnellement trouvée très utile, mais étonnamment peu fréquente chez les développeurs.
1. Mettez votre code en retrait
Comme vous le feriez à tout autre moment, dans toute autre langue, quel que soit le cas. C'est une bonne pratique pour tout le reste, et je me suis rendu compte que dans une application complexe en canevas, les choses peuvent devenir un peu confuses lorsqu'on a affaire à plusieurs contextes différents et à des états de sauvegarde/restauration. Sans oublier que le code est tout simplement plus lisible et plus propre.
Par exemple :
...
// Try to tell me this doesn't make sense to do
ctx.fillStyle = 'red';
ctx.fill();
ctx.save();
if (thing < 3) {
// indenting
ctx.beginPath();
ctx.arc(2, 6, 11, 0, Math.PI*2, true);
ctx.closePath();
ctx.beginPath();
ctx.moveTo(20, 40);
ctx.lineTo(10, 200);
ctx.moveTo(20, 40);
ctx.lineTo(100, 40);
ctx.closePath();
ctx.save();
ctx.fillStyle = 'blue'
ctx.fill();
ctx.restore();
} else {
// no indenting
ctx.drawImage(img, 0, 0, 200, 200);
ctx.save();
ctx.shadowBlur();
ctx.beginPath();
ctx.arc(2, 60, 10, 0, Math.PI*2, false);
ctx.closePath();
ctx.fillStyle 'green';
ctx.fill();
ctx.restore();
}
ctx.restore();
ctx.drawRect();
ctx.fill();
...
L'instruction IF n'est-elle pas plus facile et plus propre à lire et à savoir ce qui se passe immédiatement que l'instruction ELSE dans ce cas ? Vous voyez ce que je veux dire ? Je pense que c'est une méthode que les développeurs devraient continuer à pratiquer comme ils le feraient pour écrire du bon vieux javascript ou tout autre langage.
Utiliser requestAnimationFrame au lieu de setInterval / setTimeout
setInterval et setTimeout n'ont jamais été conçus pour être utilisés comme des minuteurs d'animation, ce sont juste des méthodes génériques pour appeler des fonctions après un délai. Si vous définissez un intervalle de 20 ms dans le futur, mais que votre file d'attente de fonctions prend plus de temps à s'exécuter, votre minuterie ne se déclenchera qu'après la fin de ces fonctions. Cela peut prendre un certain temps, ce qui n'est pas idéal en matière d'animation. RequestAnimationFrame est une méthode qui indique au navigateur qu'une animation est en cours, afin qu'il puisse optimiser les repeints en conséquence. Elle réduit également l'animation pour les onglets inactifs, afin de ne pas épuiser la batterie de votre appareil mobile si vous le laissez ouvert en arrière-plan.
Nicholas Zakas a écrit un article extrêmement détaillé et instructif. article sur requestAnimationFrame sur son blog qui vaut la peine d'être lu. Si vous souhaitez obtenir des instructions de mise en œuvre précises et rapides, alors Paul Irish a écrit une shim requestAnimationFrame - C'est ce que j'ai utilisé dans toutes les applications Canvas que j'ai créées jusqu'à récemment.
ACTUELLEMENT
Encore mieux que l'utilisation de requestAnimationFrame à la place de setTimeout et setInterval, Joe Lambert a écrit une Nouvelle cale améliorée appelés requestInterval et requestTimeout, dans lesquels il explique les problèmes qui existent lors de l'utilisation de requestAnimFrame. Vous pouvez consulter le Résumé du script. .
ACTUELLEMENT x2
Maintenant que tous les navigateurs ont rattrapé leur retard sur la spécification, il y a eu un mise à jour du polyfill requestAnimFrame() qui restera probablement celle à utiliser pour couvrir tous les vendeurs.
Utilisez plus d'une toile
Une technique pour les jeux à forte intensité d'animation qui @nicolahibbert dont il est question dans un son post sur l'optimisation des jeux Canvas mentionne qu'il peut être préférable d'utiliser plusieurs toiles superposées plutôt que de tout faire dans une seule toile. Nicola explique que "dessiner trop de pixels sur le même canevas en même temps fera chuter votre taux d'images par seconde. Prenez Breakout par exemple. Si vous essayez de dessiner les briques, la balle, la pagaie, les power-ups ou les armes, puis chaque étoile en arrière-plan, cela ne fonctionnera tout simplement pas, car il faut trop de temps pour exécuter chacune de ces instructions à tour de rôle. En divisant le champ d'étoiles et le reste du jeu sur des toiles séparées, vous pouvez garantir un framerate décent."
Rendu des éléments hors écran
J'ai dû faire cela pour quelques applications que j'ai créées, dont les suivantes L'application Facebook du projet génome olympique de Samsung . C'est une chose extrêmement utile à connaître et à utiliser, que ce soit nécessaire ou non. Elle réduit considérablement le temps de chargement, et peut s'avérer très utile pour charger des images hors écran, car elles peuvent parfois prendre du temps.
var tmpCanvas = document.createElement('canvas'),
tmpCtx = tmpCanvas.getContext('2d'),
img = document.createElement('img');
img.onload = function() {
tmpCtx.drawImage(thumbImg, 0, 0, 200, 200);
};
img.src = '/some/image/source.png';
Remarquez que le src de l'image est défini après son chargement. C'est une chose importante à ne pas oublier. Une fois que les images ont été chargées et dessinées dans ces toiles temporaires, vous pouvez les dessiner sur votre toile principale en utilisant la même ctx.drawImage(), mais au lieu de mettre l'image comme premier argument, vous utilisez 'tmpCtx.canvas' pour référencer la toile temporaire.
Autres conseils, astuces et ressources
- Cas de test Canvas
- Quelques tests supplémentaires de canvas et de JS
- Amélioration des performances de HTML5Rocks
- ** requestAnimFrame pour optimiser les événements de dragage
La toile a une référence arrière
Le contexte 2d a une référence arrière à l'élément DOM qui lui est associé :
var ctx = doc.getElementById('canvas').getContext('2d');
console.log(ctx.canvas); // HTMLCanvasElement
J'aimerais entendre d'autres personnes à ce sujet. Je travaille à l'élaboration d'une liste des éléments que nous devrions normaliser afin d'ajouter une nouvelle section au site Web de mon entreprise. Normes et meilleures pratiques en matière de code frontal . J'aimerais avoir le plus de réactions possible à ce sujet.