【问题标题】:Snap.svg traversing element treeSnap.svg 遍历元素树
【发布时间】:2017-09-22 21:39:36
【问题描述】:

我想用 Snap.svg 构建 SVG 操作 UI,不是单独发送,而是使用服务器端图形包。

我需要 Snap.svg 来加载一个外部 svg 文件,分析其结构,为其某些元素定义一些事件侦听器(基于分析)并进行一些更改。

我注意到一个元素的子元素不仅仅包含由 XML 树定义的元素。因此,对孩子的简单遍历是行不通的。

或者,.selectAll 方法假定预先了解 svg 结构。

当然,这些可以有解决方法,但我想知道我是否错过了另一种更自然的遍历结构的方法。

【问题讨论】:

  • 为什么 selectAll 假设有高级知识?
  • 您更喜欢使用哪个来加载 svg 文件:Snap.load() 还是 Snap.ajax()?
  • 关于selectAll:我的理解是它根据元素的类型或属性进行搜索。为了能够将其用于树的呼吸优先遍历(例如),您需要假设树结构以某种方式编码在属性中。关于 load() vs ajax() 我不在乎。无论如何,load() 只是对 ajax() 的调用。有什么我可以用 ajax 在解析时制作子字段来反映树结构的吗?
  • 我想我明白了问题所在。 .children() 函数继承自 node 的 Web API。因此,它包含来自 SVG 空白空间的噪声。在接缝中,Snap.svg 需要一些方法来访问元素的正确 svg 子项。我会写一个插件来做到这一点,并会在这里发布。 (除非该功能已经存在,但我错过了它。)
  • 您确定需要这样做吗?我无法完全说出您要做什么,因此我可能偏离了轨道,但是例如我很久以前就这样做了svg.dabbles.info/snaptut-loadselect-move,它可以让您单击任何元素(N 将旋转通过任何分层组元素) ,然后拖动它,它就会动画化。

标签: javascript svg snap.svg


【解决方案1】:

我在下面包含了一个通过 Snap.ajax() 调用 svg 文件的示例。它显示了两个 SVG 绘图。它将响应作为单个片段放置在绘图 Fragment SVG 中。它还允许 XML 方法访问/编辑单个元素,并将元素片段添加到其他绘图 XML SVG

这有帮助吗?

<!DOCTYPE HTML>

<html>

<head>
  <title>Snap.ajax()</title>
<script type="text/javascript" src="http://svgDiscovery.com/_SNP/snap.svg-min.js"></script>
</head>

<body onload=loadXML()>
This loads an .svg file via Snap.ajax(). It places the response as single fragment in <b>Fragment SVG</b>. It also allows XML methods to access/edit individual elements, and adds element fragments into <b>XML SVG</b>.

 <center>
 <b>Fragment SVG</b>
 <div id=fragDiv style='border:1px solid black;width:500px;height:500px'>
<svg id=fragSVG width=500 height=500 ></svg>
 </div>
  <b>XML SVG</b>
 <div id=xmlDiv style='border:1px solid black;width:500px;height:500px'>
<svg id=xmlSVG width=500 height=500 ></svg>
 </div>
</center>
<script>
 var SNPsvgFrag = Snap("#fragSVG");
 var SNPsvgXML = Snap("#xmlSVG");


//---onload---
function loadXML()
{
    var svgFile="http://svgDiscovery.com/SVGFiles/Logo.svg"

    var xml=Snap.ajax(svgFile,function()
    {
        //---insert as one fragment---
        var xmlString=xml.responseText
        var fragment=Snap.fragment(xmlString)
        SNPsvgFrag.append(fragment)

        //---DOMParser---
        var parser = new DOMParser();
        var XMLdoc=parser.parseFromString(xmlString,"text/xml").documentElement;

        for(var k=0;k<XMLdoc.childNodes.length;k++)
        {
            var elem=XMLdoc.childNodes.item(k)

            console.log(elem.nodeName)

            if(elem.nodeName=="circle")
                elem.setAttribute("fill","red")

            //---each element inserted as a fragment---
            var elemString=new XMLSerializer().serializeToString(elem)

            var elemFrag=Snap.fragment(elemString)
            SNPsvgXML.append(elemFrag)
        }
    })
}

</script>
</body>
</html>

【讨论】:

  • 谢谢!我的目标是完全通过 Snap.svg 框架的抽象来操作 svg 代码。从概念上讲,我想将任务视为碰巧在 SVG 中编码的几何+属性+行为,而不是碰巧对几何进行编码的 XML。我想镜像服务器端向量引擎的逻辑组织,这样可以简化通信,并且项目可以更具可扩展性。到目前为止,我发现的最佳解决方案是获取元素的子元素并过滤掉不应该存在的元素,例如“#text”类型的元素。这不优雅。
  • @Vakarelov 通常“机器编码”svg 不包含#text 元素。即,它都在一条线上。我期待着你解决这个应用程序,并将其发布在这里。您使用的是哪个服务器?
  • 确实,可以通过这种方式克服问题,但这并不可靠。我正在研究 snap.svg 代码,我会看到希望是创建更好的几何抽象层的好方法。关于服务器端,它是我正在编写的基于 php 的专有矢量图形引擎。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多