通过 JavaScript 访问 SVG 数据
我正在开发一个使用 SVG 和 SVG 的 Web 应用程序。 JS。一切进展顺利,但我对数据处理有点困惑。
用户创建的对象的数据会动态附加到 SVG 根。哪里&这个 SVG 数据是如何存储的,&我怎样才能访问它?我想阅读它的原因是我想将此 SVG 数据转换为 HTML5 画布(使用 Google 的 canvg< /a>),最后将其转换为 png 图像以存储在我们的数据库中以供参考。
任何指导将不胜感激。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当 Web 浏览器加载 SVG 文件时,它(粗略地)解析字节流并在内存中为 SVG 文件创建 DOM 结构。当脚本动态创建新元素并将其附加到文档时,正是这种内存中的表示形式被修改。
您可以在这里看到一个非常简单的示例:
http://phrogz.net/svg/svg_in_xhtml5.xhtml
SVG 文件在脸部背景中加载一个圆圈,然后 JavaScript 动态创建眼睛和鼻子,并将它们附加为 SVG 元素的子元素。
据我所知,您可以通过三种方式访问此信息并将其放入画布中:
您可以自己遍历元素的 DOM,并发出画布上下文绘制命令:
有关属性和方法的更多信息,请参阅 SVG DOM 参考您可以使用,或者仅使用 DOM 2 Core 方法获取属性。为简单起见,您可能希望使用后者。
例如,您可以通过
var cx = Kid.cx.baseVal.value; 使用 SVG DOM 访问圆的当前(非 SMIL 动画)
cx
code> 或者您可以更简单地执行var cx = Kid.getAttribute('cx');
。这将很简单,因为 SVG 和 Canvas 有类似的命令(例如
rect
或line
),但它们不完全匹配时需要做一些工作(例如,circle
与arcTo
、polyline
作为一系列lineTo
命令),并且为做了大量工作code>path
元素及其许多绘图命令。根据这个答案和本文,使用
XMLSerializer
接口将 SVG 作为标记返回,直接将其用作img
的源,然后将其drawImage
绘制到画布上。使用我上面的例子:如果您在 XHTML 中有 SVG(如我的示例),序列化将不会捕获 SVG 块外部定义的样式(如我的示例),因此它们不会应用于图像中。
请注意,每个这个问题/answer(我的),如果您想要 IE9,则必须先设置
onload
属性,然后再将src
设置为数据 URL兼容性。不幸的是,由于可能是也可能不是错误,将 data-url 图像绘制到画布上会导致 origin-clean 标志被设置为
false
,这意味着您将无法在画布上调用toDataURL()
画布并恢复您的 PNG。所以...我想,为了满足您对客户端修改的 SVG->Canvas->PNG-on-server 的特定需求,您将需要使用上面的第一步来序列化
svg_xml
然后将该原始源传递给 canvg。或者,您可以考虑按照上述序列化 SVG 并将其直接提交到您的服务器并执行 服务器端 SVG 到 PNG 转换。
When a web browser loads an SVG file, it (roughly) parses the stream of bytes and creates a DOM structure in memory for the SVG file. It is this in-memory representation that is modified when script dynamically creates and appends new elements to the document.
You can see a very simple example of this here:
http://phrogz.net/svg/svg_in_xhtml5.xhtml
The SVG file loads with a circle in the background for the face, and then JavaScript dynamically creates the eyes and nose and appends them as children of the SVG element.
There are three ways I know of that you can access this information and get it into a canvas:
You can walk the DOM of elements yourself, and issue canvas context drawing commands:
See the SVG DOM reference for more information on the properties and methods available to you, or just use the DOM 2 Core methods to fetch properties. For simplicity, you might want to use the latter.
For example, you can either access the current (non-SMIL animated)
cx
of the circle using the SVG DOM viavar cx = kid.cx.baseVal.value;
or you can more simply dovar cx = kid.getAttribute('cx');
.This is going to be simple where SVG and Canvas have similar commands (e.g.
rect
orline
), a little bit of work where they don't match exactly (e.g.circle
versusarcTo
,polyline
as a series oflineTo
commands), and a lot of work for thepath
element and its many drawing commands.Per this answer and this paper, use the
XMLSerializer
interface to get the SVG back as markup, use that directly as the source of animg
, and thendrawImage
that to the canvas. Using my above example:If you have SVG in XHTML (as in my example), the serialization will not capture styles defined outside of the SVG block (as in my example) and so they will not be applied in the image.
Note that per this question/answer (mine), you must set the
onload
attribute before you set thesrc
to the data URL if you want IE9 compatibility.Unfortunately, due to what may or may not be a bug, drawing a data-url image to a canvas causes the origin-clean flag to be set to
false
, which means that you will not be able to calltoDataURL()
on the canvas and get your PNG back. So...I suppose for your specific needs of Client-modified SVG->Canvas->PNG-on-server you will need to use the first step above to serialize the
svg_xml
and then pass that raw source to canvg.Alternatively, you might consider serializing the SVG per the above and submitting that directly to your server and doing server-side SVG-to-PNG conversion.
@Phrogz 答案中提到的 webkit bug 似乎已在更新的版本中修复,所以我找到了一个不需要手动解析的解决方案,它
需要
https://code.google.com/p/svgfix/ 和 https://code.google.com/p/canvg/ 并使用 d3.js 获取 svg 源,这在没有 d3.js 的情况下也应该是可行的(但这需要添加所需的元数据,这在丢失时可能会导致问题)。
The webkit bug mentioned in @Phrogz answer seems to have been fixed in more recent versions, so I found a solution that doesn't require a manual parse is
which requires
https://code.google.com/p/svgfix/ and https://code.google.com/p/canvg/ and uses d3.js to obtain the svg source, which should be doable without d3.js as well (but this takes care of adding required metadata which can lead to problems when missing).