Injecter du SVG directement dans du HTML 5

J’ai commencé à bidouiller une petite lib JavaScript capable de générer des charts en SVG (graphiques statistiques). Générer les graphiques en SVG n’est pas très dur, il suffit de quelques calculs mathématiques. En revanche ce qui m’a posé problème, c’est injecter le SVG dans la page HTML depuis le JavaScript. Je me suis alors penché sur l’intégration de SVG dans du HTML 5.

Images SVG

Afficher des images SVG externes est plutôt facile, il suffit d’utiliser la balise <object> ou la balise <iframe> , comme ceci :

<object type="image/svg+xml" data="chart.svg" width="120" height="40">
  <p>Votre navigateur ne supporte pas le SVG.</p>
</object>

SVG dans du XHTML

En revanche injecter du SVG directement dans le HTML est un peu plus sport. Historiquement il faut passer en XHTML et servir ses pages en utilisant le mimetype associé : application/xhtml+xml. Passant sur un format XML il est possible d’insérer du XML dans du XML. Dans notre cas : du SVG dans du XHTML (ça marche aussi pour du MathML).

<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" >
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:svg="http://www.w3.org/2000/svg">
<body>
  <svg xmlns="http://www.w3.org/2000/svg" width="120" height="40">
    <rect x="10" y="10" width="100" height="20" style="fill:#000"/>
  </svg>
</body>
</html>

La contrepartie de cette technique c’est qu’il faut que les pages soient bien formées. Le moindre bug XML et l’affichage se réduit à une erreur de parsing. Outch.

SVG dans du HTML 5

Heureusement j’ai découvert il y a quelques jours une technique (presque) valide en HTML 5 et qui marche sur tous les navigateurs supportant le SVG. L’astuce consiste à déclarer la doctype HTML 5 tout en spécifiant les espaces de noms XHTML et SVG sur les balises html et svg, au besoin :

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
  <svg xmlns="http://www.w3.org/2000/svg" width="120" height="40">
    <rect x="10" y="10" width="100" height="20" style="fill:#000"/>
  </svg>
</body>
</html>

Le SVG s’affiche alors correctement, et l’affichage de la page ne plante plus à la moindre erreur de parsing. Glop.

À noter cependant que pour être valide et conforme HTML 5, il faut alors servir ses pages avec le prologue XML <?xml version="1.0"?>, ainsi qu’avec le mimetype application/xhtml+xml. Le problème c’est que nos pages vont à nouveau être du XML et plus du HTML. C’est donc à vous de choisir : être valide et risquer des erreurs de parsing ; ou ne pas être valide.

Générer du SVG depuis JavaScript

Cette dernière technique est la seule qui soit aisée à utiliser lorsqu’on souhaite scripter la création du SVG (en JavaScript par ex) :

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
  <script type="text/javascript">
  svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  svg.setAttribute('width', 120);
  svg.setAttribute('height', 40);
  document.body.appendChild(svg);
  </script>
</body>
</html>

Pour générer ensuite des éléments à ajouter à notre objet svg, il faut utiliser document.createElementNS. Ensuite c’est de la DOM bien classique (et c’est ça qui est génial avec SVG). Par exemple :

var rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
rect.setAttribute('x', 10);
rect.setAttribute('y', 10);
rect.setAttribute('width', 200);
rect.setAttribute('height', 20);
svg.appendChild(rect);

Autre solution :

Au départ j’étais parti sur l’utilisation de la balide object, qui demande d’utiliser un fichier externe (contenant uniquement la déclaration SVG) ou une data-URI pour afficher le SVG initial. D’ailleurs le data-URI n’est pas possible, car Webkit refuse tout mimetype navigable dans les data-URI, ce qui oblige donc à utiliser un fichier externe. Il faut aussi ajouter un évènement load sur notre object pour savoir quand on peut commencer à ajouter des éléments, etc.

Cette solution marche aussi, mais fort compliquée. Je pensais alors que SVG était particulièrement pénible à injecter dans les pages HTML, comparé à la balise CANVAS par exemple. Bah j’avais tord, en fait c’est super simple avec HTML 5 :)

About these ads

6 Réponses to “Injecter du SVG directement dans du HTML 5”

  1. Raf Says:

    Super tuto ! ce qui est étrange c’est que ça ne semble pas fonctionner ( testé sur linux avec Firefox 3.6, Chromium 5.0.376 , et Opera 10.10.

    En fait j’ai juste recopié l’exemple html5 :

  2. Julien Says:

    En effet, écrire directement du SVG dans du HTML5 ne marche pas, alors que l’injection en JavaScript dans la page marche parfaitement…

  3. Julien Says:

    En effet, les navigateurs actuels ne supportent pas directement l’inclusion de SVG dans du HTML5 — ce qu’ils vont devoir faire car SVG et MathML sont intégrés dans la spec. HTML5. Pour le moment il ne supporte que si le HTML est servi en utilisant le content-type XHTML, et ce quelque soit le doctype spécifié (XHTML ou HTML5).

    Par exemple en enregistrant l’example HTML5 de cet article dans svg.xhtml le SVG s’affiche, en revanche en l’enregistrant dans svg.html ça ne marche plus.

    Cela prouve donc qu’il n’est pas si facile de mélanger SVG et HTML facilement. Ce n’est donc pas demain la veille que nous aurons le loisir de créer des interfaces en SVG dans du HTML :)

    En revanche l’injection de SVG en JavaScript est possible quelque soit le doctype et le content-type ! Il est donc possible d’écrire des libs JS générant du SVG sans prise de tête.

    Une solution pour générer du SVG côté serveur pourrait être de générer un JSON sur le serveur, qui sera utilisé par une lib JS pour injecter le SVG dans la page.

  4. Raf Says:

    Merci de ces précisions, en effet en js ça fonctionne mieux

  5. madsenfr Says:

    D’après mes tests (http://w3c.html5.free.fr/news/svg.php), les images SVG peuvent être intégrées dans le code HTML5 simplement via la balise (sauf pour Firefox).
    De plus, le validateur du W3C n’exige pas "" en tête de fichier (cf. http://validator.w3.org/check?uri=http://w3c.html5.free.fr/news/_svg.xhtml).

  6. madsenfr Says:

    D’après mes tests (http://w3c.html5.free.fr/news/svg.php), les images SVG peuvent être intégrées dans le code HTML5 simplement via la balise <img> (sauf pour Firefox).
    De plus, le validateur du W3C n’exige pas <?xml version="1.0"?> en tête de fichier (cf. http://validator.w3.org/check?uri=http://w3c.html5.free.fr/news/_svg.xhtml).

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s


Suivre

Recevez les nouvelles publications par mail.

%d bloggers like this: