Javascript 如何将内联svg(在DOM中)绘制到画布?

Javascript 如何将内联svg(在DOM中)绘制到画布?,javascript,html,canvas,svg,png,Javascript,Html,Canvas,Svg,Png,嗯,我需要一些关于将.svg文件/图像转换为.png文件/图像的帮助 我的页面上显示了一个.svg图像。它保存在我的服务器上(作为.png文件)。我需要按需将其转换为.png文件(单击按钮),并将.png文件保存在服务器上(我将使用.ajax请求完成此操作) 但问题是转换 我读了很多关于html5画布的东西,这可能有助于我现在需要做的事情,但我找不到任何明确的解决方案,而且,tbh,我不理解我发现的一切。。。因此,我需要一些明确的建议/帮助,告诉我如何去做 以下是“html创意”模板: <

嗯,我需要一些关于将.svg文件/图像转换为.png文件/图像的帮助

我的页面上显示了一个.svg图像。它保存在我的服务器上(作为.png文件)。我需要按需将其转换为.png文件(单击按钮),并将.png文件保存在服务器上(我将使用.ajax请求完成此操作)

但问题是转换

我读了很多关于html5画布的东西,这可能有助于我现在需要做的事情,但我找不到任何明确的解决方案,而且,tbh,我不理解我发现的一切。。。因此,我需要一些明确的建议/帮助,告诉我如何去做

以下是“html创意”模板:

<html>
    <body>
        <svg id="mySvg" width="300px" height="300px">
            <!-- 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>

$(“body”)。在(“单击”,“按钮”,函数()上){
var svgText=$(“#myViewer”).outerHTML;
var myCanvas=document.getElementById(“canvas”);
var ctxt=myCanvas.getContext(“2d”);
});

然后,我需要将svg绘制到画布中,获取base64数据,并将其保存在服务器上的.png文件中。。。但是怎样?我读到很多不同的解决方案,我实际上。。。迷路的我正在做一个JSFIDLE,但我实际上。。。没有。。。感谢阅读/帮助

有关内联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
处理程序)


另外,请记住使用
宽度
高度
属性设置画布大小,或者使用属性从JavaScript设置画布大小。

我很久以前就遇到过这个问题,因为接受的答案可能会产生不良行为

@K3N解决方案几乎是正确的,但我反对使用
svgElement.outerHTML

相反,人们应该更愿意这样做

此外,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图像[…]被保存[…]为一个.png文件'这是如何工作的?!请看一下我提供的结帐单。它应该可以解决您的问题这在这里和JSFIDLE上都是完美的。。。。但是当我尝试在我的项目中使用它时,它看起来好像绘图功能不起作用…@Julo0sS您在控制台中遇到了什么错误?是否添加了onerror处理程序?尝试插入各个阶段的console.log,并查看代码停止的位置。输出变量以查看它们是否实际包含数据或未定义。检查您是否正确获取SVG outerHTML。我的2美分。语法
self.URL | | | self.webkitURL | | | self
的含义是什么?你能解释一下这个表达式的作用吗?@K3N你如何在
console.log(canvas.toDataURL())中获得
canvas
?此答案的问题是,只有一部分生成的图像显示为转换为png图像,而不是整个svg图像。我尝试了前面的答案,如果svg没有“xmln”属性,它将失败。@kaido的答案是一个很好的改进,并且与“格式错误”的SVG一起工作。@user305883,感谢您的反馈。只是想让您知道,
元素在附加到HTML文档时不必有
xmlns
声明。所以您的SVG没有“格式错误”,只是它是一个SVG元素,而不是一个SVG文档。dataURI应该表示一个文档,因此失败。XMLSerializer()确实为我们处理转换。嘿,伙计们,很抱歉在已经回答的问题上把这个问题拖了上来。我按照这封信的回答,一切都很顺利,除了当我到达
canvas.toDataURL()
时,我得到了一个
SecurityError
。我正在使用此方法将Highcharts.js svg转换为png,因此我不确定CORS问题的来源(据我所知,这是CORS问题???)Highcharts svg都在浏览器中呈现。@MartinOLeary这不是CORS问题。在画布上绘制某些svg元素时,某些UAs具有安全限制。在哪个浏览器上会发生这种情况?如果IE
节点必须具有绝对设置的
宽度
高度
属性(而不是像
%
这样的相对属性); 请注意,IE没有在指向svg文档的HTMLImages上设置
宽度
高度
(以及它们的
naturalXXX
等价物):对于此浏览器,您需要自己从svg标记或in文档节点的
offsetXXX
获取宽度;注意,当svg通过
drawImage
绘制到画布上时,所有IE
元素时,Safari>=9确实会污染画布。