Dessiner un fichier SVG sur un canevas HTML5


131

Existe-t-il un moyen par défaut de dessiner un fichier SVG sur un canevas HTML5? Google Chrome prend en charge le chargement du SVG en tant qu'image (et simplement l'utilisation drawImage), mais la console du développeur l'avertit resource interpreted as image but transferred with MIME type image/svg+xml.

Je sais qu'une possibilité serait de convertir le SVG en commandes de canevas (comme dans cette question ), mais j'espère que ce n'est pas nécessaire. Je me fiche des anciens navigateurs (donc si FireFox 4 et IE 9 supportent quelque chose, c'est assez bien).


4
Cette question a la réponse avec une démo en direct stackoverflow.com/questions/5495952/…
Drew LeSueur

Réponses:


122

EDIT 16 déc.2019

Path2D est pris en charge par tous les principaux navigateurs maintenant

EDIT 5 novembre 2014

Vous pouvez maintenant utiliser ctx.drawImagepour dessiner des HTMLImageElements qui ont une source .svg dans certains mais pas tous les navigateurs . Chrome, IE11 et Safari fonctionnent, Firefox fonctionne avec certains bogues (mais les a corrigés tous les soirs).

var img = new Image();
img.onload = function() {
    ctx.drawImage(img, 0, 0);
}
img.src = "http://upload.wikimedia.org/wikipedia/commons/d/d2/Svg_example_square.svg";

Exemple en direct ici . Vous devriez voir un carré vert dans la toile. Le deuxième carré vert sur la page est le même <svg>élément inséré dans le DOM pour référence.

Vous pouvez également utiliser les nouveaux objets Path2D pour dessiner des chemins SVG (chaîne). En d'autres termes, vous pouvez écrire:

var path = new Path2D('M 100,100 h 50 v 50 h 50');
ctx.stroke(path);

Exemple en direct de cela ici.


Ancienne réponse de la postérité:

Il n'y a rien de natif qui vous permet d'utiliser nativement les chemins SVG dans le canevas. Vous devez vous convertir ou utiliser une bibliothèque pour le faire pour vous.

Je suggérerais de chercher à canvg:

http://code.google.com/p/canvg/

http://canvg.googlecode.com/svn/trunk/examples/index.htm


4
Pourquoi est-ce nécessaire? SVG semble dessiner parfaitement sur une toile avec juste drawImage. Mais je reçois toujours cet avertissement. D'où est ce que ça vient?
shoosh le

1
Simon, ce que tu dis n'est pas correct. Et deuxièmement, c'est un bogue confirmé dans Chrome.
Mathias Lykkegaard Lorenzen

4
Wikimedia n'aime pas que vous utilisiez le SVG, semble-t-il. J'ai échangé dans snapsvg.io/assets/images/logo.svg comme premier SVG disponible que j'ai trouvé. A travaillé chez FF. jsfiddle.net/Na6X5/331
Thomas

1
Vous pouvez également utiliser les URI de données pour ce faire: jsfiddle.net/020k543w
Swivel

9
Remarque: en raison d'un bug FireFox de longue date, malheureusement, les svgs qui n'ont pas les balises de largeur et de hauteur ne s'afficheront pas du tout sur le canevas. De plus, la largeur et la hauteur ne doivent pas être exprimées en pourcentage.
Hatoru Hansou

26

Désolé, je n'ai pas assez de réputation pour commenter la réponse @Matyas, mais si l'image du svg est également en base64, elle sera dessinée vers la sortie.

Démo:

var svg = document.querySelector('svg');
var img = document.querySelector('img');
var canvas = document.querySelector('canvas');

// get svg data
var xml = new XMLSerializer().serializeToString(svg);

// make it base64
var svg64 = btoa(xml);
var b64Start = 'data:image/svg+xml;base64,';

// prepend a "header"
var image64 = b64Start + svg64;

// set it as the source of the img element
img.onload = function() {
    // draw the image onto the canvas
    canvas.getContext('2d').drawImage(img, 0, 0);
}
img.src = image64;
svg, img, canvas {
  display: block;
}
SVG

<svg height="40">
  <rect width="40" height="40" style="fill:rgb(255,0,255);" />
  <image xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAEX0lEQVQ4jUWUyW6cVRCFv7r3/kO3u912nNgZgESAAgGBCJgFgxhW7FkgxAbxMLwBEmIRITbsQAgxCEUiSIBAYIY4g1EmYjuDp457+Lv7n+4tFjbwAHVOnVPnlLz75ht67OhhZg/M0p6d5tD9C8SNBBs5XBJhI4uNLC4SREA0UI9yJr2c4e6QO+v3WF27w+rmNrv9Pm7hxDyHFg5yYGEOYxytuRY2SYiSCIwgRgBQIxgjEAKuZWg6R9S0SCS4qKLZElY3HC5tp7QPtmlMN7HOETUTXBJjrEGsAfgPFECsQbBIbDGJZUYgGE8ugQyPm+o0STtTuGZMnKZEjRjjLIgAirEOEQEBDQFBEFFEBWLFtVJmpENRl6hUuFanTRAlbTeZarcx0R6YNZagAdD/t5N9+QgCYAw2jrAhpjM3zaSY4OJGTDrVwEYOYw2qioigoviq5MqF31m9fg1V5fCx+zn11CLNVnufRhBrsVFE1Ihpthu4KDYYwz5YQIxFBG7duMZnH31IqHL6wwnGCLFd4pez3/DaG2/x4GNPgBhEZG/GGlxkMVFkiNMYay3Inqxed4eP33uf7Y0uu90xWkGolFAru7sZn5w5w921m3u+su8vinEO02hEWLN/ANnL2rkvv2an2yd4SCKLM0JVBsCgAYZZzrnPP0eDRzXgfaCuPHXwuEYjRgmIBlQVVLl8/hKI4fRzz3L6uWe5+PMvnHz6aa4uX+D4yYe5vXaLH86eoyoLjLF476l9oKo9pi5HWONRX8E+YznOef7Vl1h86QWurlwjbc+QpikPPfoIcZLS39pmMikp8pzae6q6oqgriqrGqS+xeLScoMYSVJlfOMTl5RXW1+5w5fJVnFGWf1/mxEMnWPppiclkTLM5RdJoUBYFZVlQ5DnZMMMV167gixKLoXXsKGqnOHnqOJ/+/CfZ+XUiZ0jTmFv5mAvf/YjEliQ2vPD8Ir6qqEcZkzt38cMRo5WruFvfL9FqpyRxQhj0qLOax5I2S08+Tu/lFiGUGOPormxwuyfMnjrGrJa88uIixeYWl776lmrzNjmw8vcG8sU7ixpHMXFsCUVg9tABjEvRgzP82j7AhbyiX5Qcv2+Bvy7dYGZ1k7efeQB/Y4PBqGBtdYvb3SFzLcfqToZc/OB1zYeBSpUwLBlvjZidmWaSB1yaYOfn6LqI/r0hyU6P+cRSlhXjbEI2zvnt7y79oqQ3qeg4g6vKjCIXehtDmi6m0UnxVnCRkPUHVNt9qkLJxgXOCYNOg34v48raPaamU2o89/KKsQ9sTSpc0JK7NwdcX8s43Ek5cnSOLC/Z2R6Rj0ra0w2W1/t0xyWn51uk2Ri1QtSO6OU5d7OSi72cQeWxKG7p/Dp//JXTy6C1Pcbc6DMpPRtjTxChEznWhwVZUCKrjCrPoPDczHLmnLBdBgZlRRWUEBR3ZKrme5TlrTGlV440Y1IrXM9qQGi6mkG5V6uza7tUIeCDElTZ1L26elX+fcH/ACJBPYTJ4X8tAAAAAElFTkSuQmCC" height="20px" width="20px" x="10" y="10"></image>
</svg>
<hr/><br/>

IMAGE
<img/>
<hr/><br/>
   
CANVAS
<canvas></canvas>
<hr/><br/>


1
Même chose avec les polices, elles doivent être intégrées dans le SVG: jsfiddle.net/ykx7kp8L/121
Sphinxxx

1
vous pourrez peut-être parcourir les imgbalises dans le svg, et simplement dessiner des images sur le canevas séparément par la suite.
luckydonald

24

Vous pouvez facilement dessiner des svgs simples sur une toile en:

  1. Assigner la source du svg à une image au format base64
  2. Dessiner l'image sur une toile

Remarque: le seul inconvénient de la méthode est qu'elle ne peut pas dessiner d'images incorporées dans le svg. (voir démo)

Manifestation:

(Notez que l'image intégrée n'est visible que dans le svg)

var svg = document.querySelector('svg');
var img = document.querySelector('img');
var canvas = document.querySelector('canvas');

// get svg data
var xml = new XMLSerializer().serializeToString(svg);

// make it base64
var svg64 = btoa(xml);
var b64Start = 'data:image/svg+xml;base64,';

// prepend a "header"
var image64 = b64Start + svg64;

// set it as the source of the img element
img.src = image64;

// draw the image onto the canvas
canvas.getContext('2d').drawImage(img, 0, 0);
svg, img, canvas {
  display: block;
}
SVG

<svg height="40">
  <rect width="40" height="40" style="fill:rgb(255,0,255);" />
  <image xlink:href="https://en.gravatar.com/userimage/16084558/1a38852cf33713b48da096c8dc72c338.png?size=20" height="20px" width="20px" x="10" y="10"></image>
</svg>
<hr/><br/>

IMAGE
<img/>
<hr/><br/>
   
CANVAS
<canvas></canvas>
<hr/><br/>


2
Existe-t-il un moyen de résoudre le problème que vous avez mentionné. Image intégrée au svg.
Vijay Baskaran

Désolé, mais je n'ai pas trouvé de solution au problème de l'image intégrée.
Matyas

D'accord. Merci Matyas :)
Vijay Baskaran


6

Comme le dit Simon ci-dessus, l'utilisation de drawImage ne devrait pas fonctionner. Mais, en utilisant la bibliothèque canvg et:

var c = document.getElementById('canvas');
var ctx = c.getContext('2d');
ctx.drawSvg(SVG_XML_OR_PATH_TO_SVG, dx, dy, dw, dh);

Cela vient du lien fourni par Simon ci-dessus, qui contient un certain nombre d'autres suggestions et indique que vous souhaitez créer un lien ou télécharger canvg.js et rgbcolor.js. Ceux-ci vous permettent de manipuler et de charger un SVG, soit via une URL, soit en utilisant du code SVG en ligne entre des balises svg, dans des fonctions JavaScript.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.