Zeichnen einer SVG-Datei auf einer HTML5-Zeichenfläche

130

Gibt es eine Standardmethode zum Zeichnen einer SVG-Datei auf eine HTML5-Zeichenfläche? Google Chrome unterstützt das Laden der SVG als Bild (und das einfache Verwenden drawImage). Die Entwicklerkonsole warnt jedoch davor resource interpreted as image but transferred with MIME type image/svg+xml.

Ich weiß, dass eine Möglichkeit darin besteht, die SVG in Canvas-Befehle zu konvertieren (wie in dieser Frage ), aber ich hoffe, dass dies nicht benötigt wird. Ältere Browser interessieren mich nicht (wenn FireFox 4 und IE 9 etwas unterstützen, ist das gut genug).

Randy Voet
quelle
4
Diese Frage hat die Antwort mit einer Live-Demo stackoverflow.com/questions/5495952/…
Drew LeSueur

Antworten:

121

EDIT 16. Dezember 2019

Path2D wird jetzt von allen gängigen Browsern unterstützt

BEARBEITEN 5. November 2014

Sie können jetzt ctx.drawImageHTMLImageElements zeichnen, die in einigen, aber nicht allen Browsern eine .svg-Quelle haben . Chrome, IE11 und Safari funktionieren, Firefox funktioniert mit einigen Fehlern (die jedoch nachts behoben wurden).

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";

Live Beispiel hier . Sie sollten ein grünes Quadrat in der Leinwand sehen. Das zweite grüne Quadrat auf der Seite ist dasselbe <svg>Element, das als Referenz in das DOM eingefügt wurde.

Sie können auch die neuen Path2D-Objekte verwenden, um SVG-Pfade (Zeichenfolgen) zu zeichnen. Mit anderen Worten, Sie können schreiben:

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

Live Beispiel dafür hier.


Antwort der alten Nachwelt:

Es gibt nichts Natives, mit dem Sie SVG-Pfade im Canvas-Bereich nativ verwenden können. Sie müssen sich selbst konvertieren oder eine Bibliothek verwenden, um dies für Sie zu tun.

Ich würde vorschlagen, in canvg zu schauen:

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

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

Simon Sarris
quelle
4
Warum wird das benötigt? SVG scheint mit just perfekt auf eine Leinwand zu zeichnen drawImage. Aber ich bekomme immer noch diese Warnung. Woher kommt das?
Shoosh
1
Simon, was du sagst, ist nicht richtig. Und zweitens ist es ein bestätigter Fehler in Chrome.
Mathias Lykkegaard Lorenzen
4
Wikimedia mag es anscheinend nicht, wenn Sie die SVG verwenden. Ich habe snapsvg.io/assets/images/logo.svg als erstes verfügbares SVG ausgetauscht, das ich gefunden habe. Arbeitete in FF. jsfiddle.net/Na6X5/331
Thomas
1
Sie können auch Daten-URIs verwenden, um dies zu tun: jsfiddle.net/020k543w
Swivel
9
Hinweis: Aufgrund eines langjährigen FireFox-Fehlers werden SVGs, denen die Tags für Breite und Höhe fehlen, leider überhaupt nicht auf der Leinwand gerendert. Auch Breite und Höhe dürfen nicht in Prozent angegeben werden.
Hatoru Hansou
25

Entschuldigung, ich habe nicht genug Ruf, um die Antwort von @Matyas zu kommentieren, aber wenn sich das Bild des SVG auch in base64 befindet, wird es in die Ausgabe gezeichnet.

Demo:

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/>

Henrique Campos
quelle
1
Dasselbe gilt für Schriftarten, die in die SVG eingebettet werden müssen: jsfiddle.net/ykx7kp8L/121
Sphinxxx
1
Möglicherweise können Sie die imgTags in der durchlaufen svgund anschließend Bilder separat auf die Leinwand zeichnen.
Luckydonald
23

Sie können einfache svgs einfach auf eine Leinwand zeichnen, indem Sie:

  1. Zuweisen der Quelle des SVG zu einem Bild im Base64-Format
  2. Zeichnen Sie das Bild auf eine Leinwand

Hinweis: Der einzige Nachteil der Methode besteht darin, dass keine in die eingebetteten Bilder gezeichnet werden können svg. (siehe Demo)

Demonstration:

(Beachten Sie, dass das eingebettete Bild nur im svg) sichtbar ist.

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/>

Matyas
quelle
2
Gibt es eine Möglichkeit, das von Ihnen erwähnte Problem zu beheben? Bild eingebettet in svg.
Vijay Baskaran
Entschuldigung, aber ich habe keine Lösung für das Problem mit eingebetteten Bildern gefunden.
Matyas
In Ordnung. Danke Matyas :)
Vijay Baskaran
6

Mozilla bietet eine einfache Möglichkeit zum Zeichnen von SVG auf Leinwand mit dem Namen " Zeichnen von DOM-Objekten in eine Leinwand ".

Nati Krisi
quelle
Dies hat den gleichen Nachteil wie bei @ Simons erster Methode: Funktioniert nicht in Firefox, Chrome OK.
Amergin
3
Ihr Link funktioniert nicht mehr. Ich interessiere mich immer noch für Mozilla Way
Alirezak
6

Wie Simon oben sagt, sollte die Verwendung von drawImage nicht funktionieren. Verwenden Sie jedoch die canvg- Bibliothek und:

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

Dies kommt von dem Link, den Simon oben bereitstellt, der eine Reihe anderer Vorschläge enthält und darauf hinweist, dass Sie entweder auf canvg.js und rgbcolor.js verlinken oder diese herunterladen möchten. Mit diesen können Sie eine SVG-Datei entweder über eine URL oder mithilfe von Inline-SVG-Code zwischen SVG-Tags in JavaScript-Funktionen bearbeiten und laden.

Max West
quelle