Desenhando um arquivo SVG em uma tela HTML5

130

Existe uma maneira padrão de desenhar um arquivo SVG em uma tela HTML5? O Google Chrome suporta o carregamento do SVG como uma imagem (e simplesmente o uso drawImage), mas o console do desenvolvedor avisa queresource interpreted as image but transferred with MIME type image/svg+xml .

Eu sei que uma possibilidade seria converter os comandos SVG para canvas (como nesta pergunta ), mas espero que isso não seja necessário. Eu não me importo com navegadores mais antigos (por isso, se o FireFox 4 e o IE 9 oferecem suporte a algo, isso é bom o suficiente).

Randy Voet
fonte
4
Esta pergunta tem a resposta com uma demonstração ao vivo stackoverflow.com/questions/5495952/…
Drew LeSueur

Respostas:

121

EDIT 16 de dezembro de 2019

O Path2D é suportado por todos os principais navegadores agora

EDIT 5 de novembro de 2014

Agora você pode usar ctx.drawImagepara desenhar HTMLImageElements que tenham uma fonte .svg em alguns navegadores, mas não em todos . Chrome, IE11 e Safari funcionam, o Firefox trabalha com alguns erros (mas todos os dias foram corrigidos).

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

Exemplo ao vivo aqui . Você deve ver um quadrado verde na tela. O segundo quadrado verde na página é o mesmo<svg> elemento inserido no DOM para referência.

Você também pode usar os novos objetos Path2D para desenhar caminhos SVG (string). Em outras palavras, você pode escrever:

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

Exemplo ao vivo disso aqui.


Resposta antiga da posteridade:

Não há nada nativo que permita o uso nativo de caminhos SVG na tela. Você deve se converter ou usar uma biblioteca para fazer isso por você.

Eu sugiro procurar no canvg:

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

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

Simon Sarris
fonte
4
Por que isso é necessário? SVG parece desenhar perfeitamente em uma tela com apenas drawImage. Mas ainda recebo esse aviso. De onde isso vem?
shoosh 21/02
1
Simon, o que você está dizendo não está correto. E segundo, é um bug confirmado no Chrome.
Mathias Lykkegaard Lorenzen
4
A Wikimedia não gosta de você usar o SVG, ao que parece. Eu troquei em snapsvg.io/assets/images/logo.svg como o primeiro disponível SVG eu encontrei. Trabalhou em FF. jsfiddle.net/Na6X5/331
Thomas
1
Você também pode usar URIs de dados para fazer isso: jsfiddle.net/020k543w
Swivel
9
Nota: devido a um bug antigo do FireFox, infelizmente, svgs que não possuem as tags de largura e altura não serão renderizados na tela. Além disso, largura e altura não devem estar em porcentagens.
Hatoru Hansou
26

Desculpe, não tenho reputação suficiente para comentar a resposta @Matyas, mas se a imagem do svg também estiver em base64, ela será atraída para a saída.

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
fonte
1
A mesma coisa com fontes, eles precisam ser incorporados no SVG: jsfiddle.net/ykx7kp8L/121
Sphinxxx
1
você pode percorrer as imgtags no diretóriosvg e apenas desenhar as imagens na tela separadamente posteriormente.
luckydonald
24

Você pode facilmente desenhar svgs simples em uma tela:

  1. Atribuindo a origem do svg a uma imagem no formato base64
  2. Desenhando a imagem em uma tela

Nota: A única desvantagem do método é que ele não pode desenhar imagens incorporadas nosvg . (veja demonstração)

Demonstração:

(Observe que a imagem incorporada é visível apenas na 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/>

Matyas
fonte
2
Existe alguma maneira de corrigir o problema que você mencionou. Imagem incorporada em svg.
Vijay Baskaran
Desculpe, mas não encontrei uma solução para o problema da imagem incorporada.
Matyas
OK. Obrigado Matyas :)
Vijay Baskaran
6

O Mozilla possui uma maneira simples de desenhar SVG na tela chamada " Desenhando objetos DOM em uma tela "

Nati Krisi
fonte
Isso tem a mesma desvantagem do primeiro método do @ Simon: não funciona no Firefox, o Chrome está OK.
Amgrej
3
Seu link não funciona mais. Eu ainda interessado em Mozilla maneira
Alirezak
6

Como Simon disse acima, usar drawImage não deve funcionar. Mas, usando a biblioteca canvg e:

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

Isso vem do link que o Simon fornece acima, que contém várias outras sugestões e indica que você deseja vincular ou fazer o download de canvg.js e rgbcolor.js. Isso permite que você manipule e carregue um SVG, via URL ou usando código SVG embutido entre tags svg, nas funções JavaScript.

Max West
fonte