如何将内联 svg(在 DOM 中)绘制到画布上?
Posted
技术标签:
【中文标题】如何将内联 svg(在 DOM 中)绘制到画布上?【英文标题】:How to draw an inline svg (in DOM) to a canvas? 【发布时间】:2015-01-29 13:41:42 【问题描述】:好吧,我需要一些关于将 .svg 文件/图像转换为 .png 文件/图像的帮助...
我的页面上显示了一个 .svg 图像。它保存在我的服务器上(作为 .png 文件)。我需要根据需要将其转换为 .png 文件(单击按钮)并将 .png 文件保存在服务器上(我将使用 .ajax 请求执行此操作)。
但问题在于转换。
我阅读了很多关于 html5 Canvas 的内容,这可能有助于完成我现在需要做的事情,但我找不到任何明确的解决方案来解决我的问题,而且,tbh,我不明白我发现的所有内容。 . 所以我需要一些关于我必须做的方式的明确建议/帮助。
这里是“html idea”模板:
<html>
<body>
<svg id="mySvg" >
<!-- my svg data -->
</svg>
<label id="button">Click to convert</label>
<canvas id="myCanvas"></canvas>
</body>
</html>
还有一些js:
<script>
$("body").on("click","#button",function()
var svgText = $("#myViewer").outerHTML;
var myCanvas = document.getElementById("canvas");
var ctxt = myCanvas.getContext("2d");
);
</script>
然后,我需要将 svg 绘制到 Canvas 中,取回 base64 数据,并将其保存在我的服务器上的 .png 文件中......但是......如何?我读到了很多不同的解决方案,我实际上……迷路了……我正在研究一个 jsfiddle,但我实际上……无处可去……http://jsfiddle.net/xfh7nctk/6/……感谢阅读/帮助
【问题讨论】:
‘一个 .svg 图像 [...] 被保存 [...] 为一个 .png 文件‘这是如何工作的?! 看看***.com/a/3769883/783219 请查看我在此处提供的this answer。它应该可以解决您的问题 【参考方案1】:自从这个问题提出了一些其他问题后,我才来很久,因为接受的答案可能会产生不良行为。
@K3N 解决方案几乎是正确的,但我会反对使用svgElement.outerHTML
。
相反,人们应该更喜欢new XMLSerializer().serializeToString(svgElement)
。
此外,不需要使用 blob 和 URL API,简单的 dataURI 具有更好的跨浏览器兼容性。
所以一个完整的版本应该是:
function drawInlineSVG(svgElement, ctx, callback)
var svgURL = new XMLSerializer().serializeToString(svgElement);
var img = new Image();
img.onload = function()
ctx.drawImage(this, 0, 0);
callback();
img.src = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgURL);
// usage:
drawInlineSVG(document.querySelector('svg'), ctxt, function()
console.log(canvas.toDataURL())
);
【讨论】:
我尝试了上一个答案,如果 SVG 没有 'xmln' 属性,它将失败。 @Kaiido 的答案是一个很好的改进,并且也适用于“格式错误”的 SVG。 @user305883,感谢您的反馈。只是为了让您知道<svg>
元素在附加到 HTML 文档时不必有 xmlns
声明。所以你的 SVG 不是“格式错误”,只是它是一个 svg 元素,而不是一个 svg 文档。 dataURI 应该代表一个文档,因此失败。 XMLSerializer() 确实为我们处理了转换。
大家好 - 很抱歉将这个问题拖到已经回答的问题上。我正在关注这封信的回答,一切正常,除了当我到达 canvas.toDataURL()
时,我得到的是 SecurityError
。我正在使用这种方法将 Highcharts.js svg 转换为 png,所以我不确定 CORS 的问题出在哪里(从我读过的内容来看,这是一个 CORS 问题??) highcharts svg 全部呈现在浏览器中.
@MartinOLeary 这不是 CORS 问题。在画布上绘制一些 svg 元素时,一些 UA 有安全限制。这发生在哪个浏览器上?如果 IE
@TanyaGupta,注意根<svg>
节点必须绝对设置width
和height
属性(不是像%
这样的相对属性);请注意,IE 没有在指向 svg 文档的 HTMLImage 上设置 width
或 height
(也没有设置它们的 naturalXXX
等效项):对于此浏览器,您需要自己获取宽度,或者从svg 标记,来自 in 文档节点的 offsetXXX
;请注意,当通过 drawImage
将 svg 绘制到画布时,所有 IE <foreignObject> 元素时,Safari >= 9 确实会污染画布。【参考方案2】:
对于内联 SVG,您需要:
将 SVG 字符串转换为Blob
获取 Blob 的 URL
创建一个图像元素并将 URL 设置为src
加载后 (onload
),您可以在画布上将 SVG 绘制为图像
使用 toDataURL()
从画布中获取 PNG 文件。
例如:
function drawInlineSVG(ctx, rawSVG, callback)
var svg = new Blob([rawSVG], type:"image/svg+xml;charset=utf-8"),
domURL = self.URL || self.webkitURL || self,
url = domURL.createObjectURL(svg),
img = new Image;
img.onload = function ()
ctx.drawImage(this, 0, 0);
domURL.revokeObjectURL(url);
callback(this);
;
img.src = url;
// usage:
drawInlineSVG(ctxt, svgText, function()
console.log(canvas.toDataURL()); // -> PNG data-uri
);
当然,这里的console.log只是举例。而是在此处存储/传输字符串。 (我还建议在方法中添加一个onerror
处理程序)。
还记得使用width
和height
属性设置画布大小,或者使用属性从javascript 设置。
【讨论】:
这在 JSFiddle 和 JSFiddle 上都很完美......但是当我尝试在我的项目中使用它时,看起来绘图功能不起作用...... @Julo0sS 您在控制台中遇到了什么错误?你添加了一个 onerror 处理程序吗?尝试为各个阶段插入 console.log 并查看代码停止的位置。输出变量以查看它们是否实际包含数据或未定义。检查您是否正确抓取了 SVG outerHTML。我的 2 美分。 语法self.URL || self.webkitURL || self
的含义是什么,你能解释一下这个表达式的作用吗?
@K3N 你如何在console.log(canvas.toDataURL());
中得到canvas
?
这个答案的问题是只有一部分 ger=nerated 图像出现转换为 png 图像,而不是整个 svg 图像转换以上是关于如何将内联 svg(在 DOM 中)绘制到画布上?的主要内容,如果未能解决你的问题,请参考以下文章