Javascript 从canvas元素获取SVG并保存

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10273516/
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-24 00:37:48  来源:igfitidea点击:

Get SVG from canvas element and save it

javascriptcanvassvgsave

提问by kaiser

Currently I'm creating a small application for a friend, who′s starting his PhD and needs to build some network graphs. So far everything works fine using the a Force Directed graph. The graphs nodes can be moved to style the layout.

目前我正在为一个朋友创建一个小应用程序,他正在攻读博士学位,需要构建一些网络图。到目前为止,使用力有向图一切正常。可以移动图形节点以设置布局样式。

The thing I can't get my head around is:

我无法理解的是:

?how to extract the data from the canvas and save it to a SVG file?.

?如何从画布中提取数据并将其保存到 SVG 文件中?.

What I tried:

我试过的:

I already tried accessing the image Data from the console with

我已经尝试从控制台访问图像数据

var app.canvas = document.getElementById( 'graph-canvas' )
    .getContext( '2d' )
        .getImageData( 0, 0, 200, 200 );

and got an (object) ImageDatain return. Now I can access the ↑ shown canvas data with app.canvas.data. (When I try too look up the values, the browser starts hanging and asks if the script should be stopped - Chrome & FF latest).

并得到了(object) ImageData回报。现在我可以访问 ↑ 显示的画布数据app.canvas.data。(当我尝试查找值时,浏览器开始挂起并询问是否应停止脚本 - Chrome 和 FF 最新版本)。

How would I go from here to get the SVG drawn and then saved by the click of a button?

我将如何从这里开始绘制 SVG,然后通过单击按钮保存?

EDIT:

编辑:

So far I found out how to draw the SVG and add an image/pngelement to it. How ever, it′s not displaying.

到目前为止,我发现了如何绘制 SVG 并向其添加image/png元素。但是,它没有显示。

// Add the test SVG el:
var svg = document.createElementNS( "http://www.w3.org/2000/svg", "svg" );
svg.setAttribute( 'style', 'border: 1px solid black;' )
        .setAttribute( 'width', '600' )
        .setAttribute( 'height', '400' )
        .setAttributeNS(
            'http://www.w3.org/2000/xmlns/',
            'xmlns:xlink',
            'http://www.w3.org/1999/xlink'
        );

// Call
importCanvas( document.getElementById( 'infovis-canvas' ), svg ); 

// Function: Add data to SVG
function importCanvas( sourceCanvas, targetSVG ) 
{
    // get base64 encoded png data url from Canvas
    var img_dataurl = sourceCanvas.toDataURL( "image/png" );

    var svg_img = document.createElementNS(
        "http://www.w3.org/2000/svg",
        "image"
    );

    svg_img.setAttributeNS(
        'http://www.w3.org/1999/xlink',
        'xlink:href',
        img_dataurl
    );
    jQuery( targetSVG.appendChild( svg_img ) )
        .appendTo( '#graph-container' );

    console.log( 'done' ); // Log & confirm
}

And finally the...

最后...

// ...resulting SVG element containing the image element
<svg style="border: 1px solid black;" width="600" height="400" xlink="http://www.w3.org/1999/xlink"><image href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABQAAA(...)


The UI works with jQuery UI, jQuery and the The Jit/InfoVIZlibrary, so those are available.

UI 与 jQuery UI、jQuery 和Jit/InfoVIZ库一起使用,因此这些都是可用的。

回答by Erik Dahlstr?m

If you want to preserve it as a vector graphic instead of as a raster, you can try one of the libraries that translate the canvas API operations to svg.

如果您想将其保留为矢量图形而不是光栅,您可以尝试将画布 API 操作转换为 svg 的库之一。

For SVGKit:

对于SVGKit

var svgkitContext = new SVGCanvas(150,150);

function draw(ctx) {
   // ... normal canvas drawing commands go here ...
}

// draw to SVGKit canvas (svg) instead of canvasElement.getContext("2d")
draw(svgkitContext);

Full running exampleof the above.

上面的完整运行示例

For canvas-svg:

对于画布 svg

var canvasSVGContext = new CanvasSVG.Deferred();
canvasSVGContext.wrapCanvas(document.querySelector("canvas"));
var canvasContext = document.querySelector("canvas").getContext("2d");

function draw(ctx) {
    // ... normal canvas drawing commands go here ...
}

// draw to html5 canvas and record as svg at the same time
draw(canvasContext);

// append the svg result
var svg = document.appendChild(canvasContext.getSVG());

Full running exampleof the above.

上面的完整运行示例

For generating svg instead:

用于生成 svg:

Another option is of course to make the graph as an svg in the first place, d3.jsis a javascript library that makes it easy to do this, see e.g this exampleof a force directed graph.

另一种选择当然是首先将图形制作为 svg,d3.js是一个 javascript 库,可以轻松做到这一点,例如,请参阅力有向图示例

回答by mihai

If you're limited to ImageDatayou're out of luck, because that's just a mere pixel array (see reference). You can't obtain a meaningful SVG image from there. You can probably pull off a .pngrepresentation...but that's a static image with no interaction.

如果您仅限ImageData于此,那您就不走运了,因为那只是一个像素阵列(请参阅参考资料)。您无法从那里获得有意义的 SVG 图像。您可能可以完成一个.png表示......但这是一个没有交互的静态图像。

If you're going to do some sort of canvas to SVG export, it's important how you're doing the canvas drawing. The best approach would be to use a library that maintains a canvas scene graph.

如果您要为 SVG 导出做某种画布,那么画布绘图的方式很重要。最好的方法是使用维护画布场景图的库。

Fabric.jsseems to be a good choice. You can do the drawing with canvas and then call canvas.toSVG()and get your svg image.

Fabric.js似乎是一个不错的选择。您可以使用画布进行绘图,然后调用canvas.toSVG()并获取您的 svg 图像。