Du dessin vectoriel dans une page web… sans Adobe Flash
Peu de personnes se sont frottées au dessin interactif dans une page web. Lorsque l’on veut dessiner de façon vectorielle (c’est à dire pour résumer que le dessin est « lisse » à toutes les échelles), on n’a pas réellement d’autre choix que d’utiliser du Flash (qui est une technologie propriétaire). Sauf si on s’intéresse au SVG, au VML, et à RaphaëlJS.
Je ne reviendrai pas sur le débat houleux entre Apple et Adobe concernant, entre autres, le portage d’un Flash Player sur les plateformes touch (iPhone, iPad, iPod touch). Cependant, il se trouve que ce dont je vais parler ici fonctionne effectivement sur mon iPhone.
Le SVG (un exemple de fichier SVG ici) c’est un format ouvert dérivé du XML destiné à décrire des tracés vectoriels. Le logiciel Inkscape, un Illustrator open-source sauvegarde les fichiers justement dans ce format. Un format XML, ça veut donc dire des éléments du DOM manipulables comme toutes les autres balises HTML!
Il existe une limite. Le SVG est bien interprété par Firefox, Opera ou Safari, mais Internet Explorer ne sait pas quoi en faire, pas avant la version 9 apparemment. Cependant, il sait afficher un autre type de description vectorielle : le VML.
C’est là qu’intervient RaphaëlJS en se positionnant comme couche d’abstraction sur le choix SVG/VML, et comme outil efficace pour la création et la manipulation des balises de dessin.
RaphaëlJS propose une interface simple pour dessiner des primitives ou des courbes paramétrées, de changer leurs paramètres, et d’animer tout ça.
Tout commence par la définition d’une surface de dessin, qu’on peut créer à partir de rien, ou bien inclure dans un élément existant. Voici un exemple :
/* Création d'une surface de dessin à l'intérieur de l'élément d'id "mondiv" et de 500 pixels de côté */ surface = Raphael("mondiv", 500, 500);
C’est ensuite cette surface qui dispose des méthodes utilisées pour le dessin
obj = surface.line(0,0,100,100);
On remarque que j’ai gardé une référence sur l’objet créé (obj), mais j’aurais très bien pu ne pas le faire. Dans mon cas, je peux réutiliser cette référence pour d’autres opérations :
obj.attr("stroke-width",5).move(50,50); // épaisseur du trait à 5 // déplacement aux coordonnées 50,50
Les opérations sur les objets de dessins revoient toujours une référence sur eux-mêmes, je peux donc enchaîner les commandes!
Je vous enjoins à aller voir les exemples sur le site de RaphaëlJS, et particulièrement le tigre ou le curver. Essayez le zoom de page pour plonger dans les détails des dessins!
Et enfin, un exemple maison. Cliquez dans l’image pour un peu d’interaction!
Et le code de tout ça, en considérant que j’ai un <div id="paper" />
dans le code HTML de ma page :
// Création de la surface de dessin. // Elle est attachée à un div dont l'id est "paper" paper = Raphael("paper", 500, 330); // Dessin de trois cercles, donc je fais varier les centres, // les diamètres, la couleur... paper.circle(250,165,200) .attr("fill", "#DDDDDD") .attr("stroke","Transparent") .attr("opacity",0.5); paper.circle(30,250,100) .attr("fill", "#DDEEFF") .attr("stroke","Transparent") .attr("opacity",0.7); paper.circle(600,50,250) .attr("fill", "#FF9999") .attr("stroke","Transparent") .attr("opacity",0.5); // Défition du callback d'événement click sur ma surface paper.canvas.onclick = function(clickevent){ //randint(min, max) renvoie un entier aléatoire r = randint(10,100); // dessin d'un cercle de taille 0 au point du clic // dont l'épaisseur du trait et la couleur son définis // et dont on anime le diamètre jusqu'à la taille finale paper.circle(clickevent.layerX,clickevent.layerY,0) .attr({"stroke-width":Math.ceil(r/5),"stroke":Raphael.getColor()}) .animate({"r":r}, Math.ceil(500 + (r-10)*4), "bounce"); };
Aussi simple que ça! En poussant un peu plus loin, on peut même faire du drag&drop sur les éléments, conditionner le dessin sur le chargement AJAX de données, ou encore utiliser jQuery pour manipuler le tout!
On a donc là une alternative à Flash plutôt intéressante. Je dirais que dans l’état actuel des choses, on peut essentiellement utiliser RaphaëlJS comme un petit outil pour facilement ajouter des décorations dans des pages, ou encore dessiner des graphes, ou manipuler des représentations de données un peu évoluées… Cependant on n’a pas de réel moteur d’exécution et de logiciel d’édition pour simplement créer et jouer une animation comme on peut le faire avec Flash… On attend qu’un éditeur logiciel fabrique ces briques manquantes!
« On attend qu’un éditeur logiciel fabrique ces briques manquantes! » ou encore qu’une bande de geeks le fasse 🙂
l’industrie va vers html5/canvas: http://en.wikipedia.org/wiki/Canvas_element
Yep tout-à-fait, j’oubliais de le mentionner… Mais le SVG, c’est quand même cool ;-)!
J’ai utilisé le Canvas avec draw2d, et je n’ai pas trop aimé. Ce qui me plait avec le SVG/VML c’est qu’on a des éléments de DOM déjà tout prêts, qui persistent le temps d’existence de la page côté client, qu’on peut même préparer d’avance en code XML en même temps que le reste de la page, puis le modifier en JS.
c’est sur 🙂