在HTML5画布上绘制SVG文件


130

是否有将SVG文件绘制到HTML5画布上的默认方法?Google Chrome支持将SVG加载为图像(并简单地使用drawImage),但是开发者控制台会对此进行警告resource interpreted as image but transferred with MIME type image/svg+xml

我知道将SVG转换为canvas命令的可能性(就像在这个问题中一样),但是我希望这不是必需的。我不在乎较旧的浏览器(因此,如果FireFox 4和IE 9支持某些功能,那就足够了)。


4
这个问题有一个实时演示stackoverflow.com/questions/5495952/…
Drew LeSueur

Answers:


121

编辑2019年12月16日

现在所有主要浏览器都支持Path2D

编辑2014年11月5日

现在,您可以在某些(但不是全部)浏览器中ctx.drawImage绘制具有.svg源的HTMLImageElement 。Chrome,IE11和Safari可以工作,Firefox可以解决一些错误(但每天晚上都可以修复)。

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

这里的例子。您应该在画布上看到一个绿色正方形。页面上的第二个绿色正方形是<svg>插入DOM中以供参考的相同元素。

您还可以使用新的Path2D对象绘制SVG(字符串)路径。换句话说,您可以编写:

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

这里的例子。


旧后代答案:

没有任何一种本机可允许您在画布中本机使用SVG路径。您必须转换自己或使用库来为您做。

我建议您浏览canvg:

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

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


4
为什么需要这个?SVG似乎可以完美地用画布绘制drawImage。但是我仍然得到那个警告。它从何而来?
shoosh

1
西蒙,你说的不对。其次,这是已确认的Chrome错误。
Mathias Lykkegaard Lorenzen 2011年

4
看来,Wikimedia不喜欢您使用SVG。我交换了snapsvg.io/assets/images/logo.svg作为我发现的第一个可用的SVG。在FF工作。jsfiddle.net/Na6X5/331
托马斯(Thomas)

1
您还可以使用数据的URI,为了做到这一点:jsfiddle.net/020k543w
旋转

9
注意:由于FireFox Bug长期存在,遗憾的是,缺少width和height标签的svg根本无法在画布上渲染。另外,宽度和高度不得以百分比为单位。
Hatoru Hansou

26

抱歉,我没有足够的声誉来评论@Matyas答案,但是如果svg的图像也位于base64中,它将被绘制到输出中。

演示:

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
与字体相同,它们需要嵌入到SVG中:jsfiddle.net/ykx7kp8L/121
Sphinxxx

1
您也许可以遍历中的img标签svg,然后再在画布上分别绘制图像。
luckydonald

23

您可以通过以下方法轻松地将simple svgs 绘制到画布上:

  1. 将svg的源分配给base64格式的图像
  2. 将图像绘制到画布上

注意:该方法的唯一缺点是无法绘制嵌入到svg。(请参见演示)

示范:

(请注意,嵌入的图片仅在中可见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
有什么办法可以解决您提到的问题。图像嵌入svg。
维杰·巴斯卡兰

抱歉,但是我还没有找到解决嵌入式图像问题的方法。
Matyas

好的。谢谢Matyas :)
Vijay Baskaran


6

正如Simon所说,使用drawImage应该行不通。但是,使用canvg库和:

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

这来自Simon上面提供的链接,其中包含许多其他建议,并指出您要链接到或下载canvg.js和rgbcolor.js。这些允许您通过URL或在JavaScript函数中使用svg标签之间的内联SVG代码来操纵和加载SVG。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.