【问题标题】:Get SVG from canvas element and save it从画布元素中获取 SVG 并保存
【发布时间】:2012-05-03 15:35:39
【问题描述】:

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

我无法理解的是:

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

我尝试了什么:

我已经尝试使用

从控制台访问图像数据
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 元素。但是,它没有显示。

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

最后...

// ...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 库一起使用,所以这些都是可用的。

【问题讨论】:

  • @mightyuhu 谢谢 - 会读一读。到目前为止,我可以访问数据(请参阅更新)。
  • @Phrogz 不。这是关于从画布 位图 导出到 SVG。 KineticJS 是 vector,导出起来非常简单。就像从 ↑ 导出到 PNG 一样简单。
  • @kaiser 感谢您的澄清;所以问题实际上是“如何在 SVG 中显示位图”和“如何从画布创建图像”。

标签: javascript canvas svg save


【解决方案1】:

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

对于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);

上面的example 完全运行。

对于canvas-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());

上面的example 完全运行。

改为生成 svg:

当然,另一种选择是首先将图形制作为 svg,d3.js 是一个 javascript 库,可以很容易地做到这一点,参见例如力有向图的 this example

【讨论】:

  • 您能否通过一个简短的示例来扩展您的答案,说明如何使用第一个库将数据放入画布对象中?在我看来,两者都更像是绘制库,我找不到任何关于如何从画布imageData 绘制 SVG 的教程或指南。
  • 埃里克,当我从你的答案中删除链接时,你的答案一点帮助都没有。你介意有一天编辑它并修复它吗?到目前为止,这个问题已经吸引了 5,000 名读者,您可能有一个解决方案......
  • 我觉得你的问题有点不清楚。您想在 svg 中简单地绘制位图(阅读:这就是 canvas 中的 ImageData)吗?或者您想从用于生成画布的命令中生成真正的矢量图形?在后一种情况下,方法是使用自定义上下文对象而不是从画布元素本身返回的正常上下文来记录命令。
  • 嗨,Erik,这个答案今天被认为是最先进的吗?感谢您的帮助!
【解决方案2】:

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

如果您打算将某种画布导出到 SVG,那么如何进行画布绘制就很重要。最好的方法是使用维护画布scene graph 的库。

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

【讨论】:

  • 看来你是对的。我想,我需要从 InfoVis 切换到像素改组的东西,但要绘制真实的向量......
  • fabric.js 的一个缺点是您需要使用该库中的方法在画布上绘图,因此您需要更改现有代码。
  • 是的,我目前正在研究其他可以绘制力有向图的库(那里没有太多)。 Fabric.js 更像是一个 canvas-plain.js 并且不在列表中。
猜你喜欢
  • 2012-11-05
  • 2021-07-27
  • 1970-01-01
  • 1970-01-01
  • 2017-12-22
  • 2018-09-16
  • 2016-04-17
  • 1970-01-01
  • 2012-07-26
相关资源
最近更新 更多