关于javascript:从canvas元素获取SVG并保存

Get SVG from canvas element and save it

目前,我正在为一个朋友创建一个小型应用程序,该朋友正在开始他的博士学位并需要构建一些网络图。到目前为止,使用力导向图可以正常工作。可以移动图形节点以设置布局样式。

我无法理解的是:

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

我试过的

我已经尝试使用以下命令从控制台访问图像数据

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

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

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

编辑:

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 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
}

最后是...

1
2
// ...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(...)

该UI与jQuery UI,jQuery和The Jit / InfoVIZ库一起使用,因此它们可用。


如果要将其保留为矢量图形而不是栅格,可以尝试使用一种将canvas API操作转换为svg的库。

对于SVGKit:

1
2
3
4
5
6
7
8
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);

上面的完整示例。

对于canvas-svg:

1
2
3
4
5
6
7
8
9
10
11
12
13
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());

上面的完整示例。

生成svg代替:

当然,另一种选择是首先使图形成为svg,d3.js是一个JavaScript库,可以很容易地做到这一点,请参见例如力导向图的示例。


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

如果要进行某种画布到SVG的导出,那么如何进行画布绘制就很重要。最好的方法是使用一个维护画布场景图的库。

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