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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27230293/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 23:53:48  来源:igfitidea点击:

How to draw an inline svg (in DOM) to a canvas?

javascripthtmlcanvassvgpng

提问by Julo0sS

Well, I need some help about convert .svg file/image to .png file/image...

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

I have a .svg image displayed on my page. It is saved on my server (as a .png file). I need to convert it to a .png file on demand (on click on a button) and save the .png file on the server (I will do this with an .ajax request).

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

But the problem is the conversion.

但问题是转换。

I read many things about the html5 Canvas, which can probably help doing what I need to do now, but I can't find any clear solution to my problem, and, tbh, I do not understand everything I found... So I need some clear advices/help about the way I have to do it.

我阅读了很多关于 html5 Canvas 的内容,这可能有助于做我现在需要做的事情,但我找不到任何明确的问题解决方案,而且,tbh,我不明白我发现的一切......所以我需要一些关于我必须做的方式的明确建议/帮助。

Here is the "html idea" template :

这是“html idea”模板:

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

and some js :

和一些js:

<script>
    $("body").on("click","#button",function(){
        var svgText = $("#myViewer").outerHTML;
        var myCanvas = document.getElementById("canvas");
        var ctxt = myCanvas.getContext("2d");
    });
</script>

Then, I need to draw the svg into the Canvas, get back the base64 data, and save it in a .png file on my server... but... how? I read about so many different solutions that I'm actually... lost... I'm working on a jsfiddle, but I'm actually... nowhere... http://jsfiddle.net/xfh7nctk/6/... Thanks for reading / help

然后,我需要将 svg 绘制到 Canvas 中,取回 base64 数据,并将其保存在我服务器上的 .png 文件中......但是......如何?我读到了很多不同的解决方案,我实际上......迷路了......我正在研究一个jsfiddle,但我实际上......无处...... http://jsfiddle.net/xfh7nctk/6 /...感谢阅读/帮助

回答by

For inline SVG you'll need to:

对于内联 SVG,您需要:

  • Convert the SVG string to a Blob
  • Get an URL for the Blob
  • Create an image element and set the URL as src
  • When loaded (onload) you can draw the SVG as an image on canvas
  • Use toDataURL()to get the PNG file from canvas.
  • 将 SVG 字符串转换为 Blob
  • 获取 Blob 的 URL
  • 创建一个图像元素并将 URL 设置为 src
  • 加载 ( onload) 后,您可以将 SVG 绘制为画布上的图像
  • 用于toDataURL()从画布中获取 PNG 文件。

For example:

例如:

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
});

Of course, console.log here is just for example. Store/transfer the string instead here. (I would also recommend adding an onerrorhandler inside the method).

当然,这里的console.log 只是举例。在这里存储/传输字符串。(我还建议onerror在方法中添加一个处理程序)。

Also remember to set canvas size using either the widthand heightattributes, or from JavaScript using properties.

还要记住使用widthheight属性设置画布大小,或使用属性从 JavaScript 设置。

回答by Kaiido

I come long after since some other question raised from this one because the accepted answer may produce undesirable behavior.

自从这个问题提出其他一些问题以来,我很久以后才来,因为接受的答案可能会产生不良行为。

@K3N solution is almost right, but I would go against the use of svgElement.outerHTML.
Instead, one should prefer new XMLSerializer().serializeToString(svgElement).

@K3N 解决方案几乎是正确的,但我会反对使用svgElement.outerHTML.
相反,人们应该更喜欢new XMLSerializer().serializeToString(svgElement).

Also, the use of blob and of the URL API is not necessary and a simple dataURI has more compatibility accross browsers.

此外,blob 和 URL API 的使用不是必需的,简单的 dataURI 具有更多的跨浏览器兼容性。

So a complete version of this would be :

所以一个完整的版本将是:

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())})