Disegnare un file SVG su una tela HTML5


131

Esiste un modo predefinito di disegnare un file SVG su un canvas HTML5? Google Chrome supporta il caricamento di SVG come immagine (e semplicemente l'utilizzo drawImage), ma la console per gli sviluppatori lo avvisa resource interpreted as image but transferred with MIME type image/svg+xml.

So che una possibilità sarebbe quella di convertire i comandi SVG in comandi canvas (come in questa domanda ), ma spero che non sia necessario. Non mi importa dei browser più vecchi (quindi se FireFox 4 e IE 9 supporteranno qualcosa, va bene).


4
Questa domanda ha la risposta con una demo live stackoverflow.com/questions/5495952/…
Drew LeSueur

Risposte:


122

EDIT 16 dic 2019

Path2D è supportata da tutti i principali browser ora

EDIT 5 novembre 2014

Ora puoi usare ctx.drawImageper disegnare HTMLImageElements che hanno una fonte .svg in alcuni ma non in tutti i browser . Chrome, IE11 e Safari funzionano, Firefox funziona con alcuni bug (ma di notte li ha risolti).

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

Esempio live qui . Dovresti vedere un quadrato verde nella tela. Il secondo quadrato verde sulla pagina è lo stesso <svg>elemento inserito nel DOM come riferimento.

È inoltre possibile utilizzare i nuovi oggetti Path2D per disegnare percorsi SVG (stringa). In altre parole, puoi scrivere:

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

Vivo esempio di questo qui.


Vecchia risposta dei posteri:

Non c'è niente di nativo che ti permetta di usare nativamente i percorsi SVG nella tela. Devi convertirti o utilizzare una libreria per farlo per te.

Suggerirei di guardare a Canvg:

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

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


4
Perché è necessario? SVG sembra disegnare perfettamente su una tela con solo drawImage. Ma ho ancora quell'avvertimento. Da dove viene?
shoosh

1
Simone, quello che stai dicendo non è corretto. E in secondo luogo, è un bug confermato in Chrome.
Mathias Lykkegaard Lorenzen,

4
Sembra che a Wikimedia non piaccia usare SVG. Ho scambiato in snapsvg.io/assets/images/logo.svg come il primo SVG disponibile che ho trovato. Ha lavorato in FF. jsfiddle.net/Na6X5/331
Thomas

1
È anche possibile utilizzare gli URI dei dati per fare ciò: jsfiddle.net/020k543w
Swivel

9
Nota: a causa di un bug FireFox di vecchia data, purtroppo, gli svg che mancano dei tag larghezza e altezza non verranno visualizzati sulla tela. Inoltre, larghezza e altezza non devono essere in percentuale.
Hatoru Hansou,

26

Spiacente, non ho abbastanza reputazione per commentare la risposta di @Matyas, ma se l'immagine di svg è anche in base64, verrà disegnata all'output.

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


1
Stessa cosa con i caratteri, devono essere incorporati nell'SVG
Sphinxxx

1
potresti essere in grado di iterare attraverso i imgtag in svg, e semplicemente disegnare immagini sulla tela separatamente in seguito.
luckydonald

24

Puoi facilmente disegnare semplici svgs su una tela:

  1. Assegnare la fonte dello svg a un'immagine in formato base64
  2. Disegnare l'immagine su una tela

Nota: l'unico inconveniente del metodo è che non è possibile disegnare immagini incorporate insvg . (vedi demo)

Dimostrazione:

(Nota che l'immagine incorporata è visibile solo nella 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
C'è un modo per risolvere il problema che hai citato. Immagine incorporata in svg.
Vijay Baskaran,

Spiacenti, ma non ho trovato una soluzione al problema dell'immagine incorporata.
Matyas,

Va bene. Grazie Matyas :)
Vijay Baskaran,


6

Come dice Simon sopra, l'utilizzo di drawImage non dovrebbe funzionare. Ma, usando la libreria canvg e:

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

Questo deriva dal link che Simon fornisce sopra, che contiene una serie di altri suggerimenti e sottolinea che si desidera collegare o scaricare canvg.js e rgbcolor.js. Consentono di manipolare e caricare un file SVG, tramite URL o utilizzando il codice SVG in linea tra tag svg, all'interno delle funzioni JavaScript.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.