【问题标题】:Access attributes of a SVG node访问 SVG 节点的属性
【发布时间】:2015-04-21 22:15:07
【问题描述】:

我有一个 SVG 文件正在显示,我想从中获取单击特定元素时的信息。

这是 SVG 的一部分:

        <g id="group327-2702" transform="translate(1539.96,-1043.15)" v:mID="327" v:groupContext="group">
        <v:custProps>
            <v:cp v:nameU="idApplication" v:lbl="idApplication" v:type="0" v:sortKey="1" v:langID="1036" v:val="VT4(143)"/>
            <v:cp v:nameU="labelFR" v:lbl="labelFR" v:type="0" v:sortKey="3" v:langID="1036" v:val="VT4(Carnet d&#39;ordres)"/>
            <v:cp v:nameU="labelEN" v:lbl="labelEN" v:type="0" v:sortKey="4" v:langID="1036"
                    v:val="VT4(Order Management System )"/>
            <v:cp v:nameU="type" v:lbl="Type" v:type="0" v:langID="1036" v:val="VT4(Business)"/>
            <v:cp v:nameU="appLevel" v:lbl="appLevel" v:type="0" v:langID="1036" v:val="VT4(3)"/>
            <v:cp v:nameU="name" v:lbl="name" v:type="0" v:sortKey="2" v:langID="1036" v:val="VT4(MCE Trading)"/>
            <v:cp v:nameU="External" v:lbl="External" v:type="0" v:langID="1036" v:val="VT4(FALSE)"/>
            <v:cp v:nameU="_VisDM_type" v:lbl="type" v:langID="1036" v:val="VT4(Business)"/>
            <v:cp v:nameU="_VisDM_status" v:lbl="status" v:type="2" v:langID="1036" v:val="VT0(1):26"/>
        </v:custProps>
        <v:userDefs>
            <v:ud v:nameU="msvStructureType" v:prompt="" v:val="VT4(Container)"/>
            <v:ud v:nameU="msvSDContainerMargin" v:prompt="" v:val="VT0(0.078740157480315):24"/>
            <v:ud v:nameU="Label" v:prompt="" v:val="VT0(2):26"/>
            <v:ud v:nameU="ShapeVersion" v:prompt="" v:val="VT0(1):26"/>
            <v:ud v:nameU="LightColorText" v:prompt="" v:val="VT0(0):5"/>
        </v:userDefs>
        <title>Module.52.327</title>
        <g id="shape328-2703" v:mID="328" v:groupContext="shape">
            <title>Feuille.328</title>
            <v:userDefs>
                <v:ud v:nameU="visVersion" v:val="VT0(14):26"/>
            </v:userDefs>
            <rect x="0" y="1652.6" width="93.5433" height="31.1811" rx="2.83465" ry="2.83465" class="st72"/>
        </g>
        <g id="shape327-2705" v:mID="327" v:groupContext="groupContent">
            <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/>
            <v:textRect cx="46.7717" cy="1668.19" width="93.55" height="31.1811"/>
            <text x="28.54" y="1661.89" class="st73" v:langID="1036"><v:paragraph v:horizAlign="1"/><v:tabList/>MCE Trading<v:newlineChar/><v:newlineChar/><tspan
                        x="7.63" dy="2.4em" class="st5">Order Management System </tspan> </text>            </g>
    </g>

我需要访问我的节点&lt;v:custProps&gt; 的第一个子节点的属性:

&lt;v:cp v:nameU="idApplication" v:lbl="idApplication" v:type="0" v:sortKey="1" v:langID="1036" v:val="VT4(143)"/&gt;

奇怪的是每个节点之间都有空的文本兄弟: 例如,如果我这样做:

var msg = "";
    msg += "target nodeName, width x height : " + evt.target.nodeName + ", " + evt.target.getAttributeNodeNS(null, 'width').nodeValue + " x " + evt.target.getAttributeNodeNS(null, 'height').nodeValue + "\n\n";

    msg += "parent nodeName, id : " + evt.target.parentNode.nodeName + ", " + evt.target.parentNode.id + "\n\n";

    msg += "parent previousSibling nodeName : " + evt.target.parentNode.previousSibling.nodeName + "\n\n";

    msg += "parent 2 previousSibling nodeName : " + evt.target.parentNode.previousSibling.previousSibling.nodeName + "\n\n";

    msg += "parent 3 previousSibling nodeName : " + evt.target.parentNode.previousSibling.previousSibling.previousSibling.nodeName + "\n\n";

    msg += "parent 4 previousSibling nodeName : " + evt.target.parentNode.previousSibling.previousSibling.previousSibling.previousSibling.nodeName + "\n\n";

    msg += "parent 5 previousSibling nodeName : " + evt.target.parentNode.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling.nodeName + "\n\n";

    msg += "parent 6 previousSibling nodeName : " + evt.target.parentNode.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling.nodeName + "\n\n";

    msg += "parent 6 previousSibling firstChild nodeName : " + evt.target.parentNode.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling.firstChild.nodeName + "\n\n";

    msg += "parent 6 previousSibling firstChild nextSibling nodeName : " + evt.target.parentNode.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling.firstChild.nextSibling.nodeName + "\n\n";

alert(msg);

结果是:

目标节点名,宽 x 高:矩形,93.5433 x 31.1811

父节点名,id:g,shape328-2703

parent previousSibling nodeName : #text

parent 2 previousSibling nodeName : title

父 3 previousSibling nodeName : #text

parent 4 previousSibling nodeName : v:userDefs

父 5 previousSibling nodeName : #text

父 6 previousSibling nodeName : v:custProps

parent 6 previousSibling firstChild nodeName : #text

parent 6 previousSibling firstChild nextSibling nodeName : v:cp

所以现在我(以一种奇怪的方式)访问了我的节点&lt;v:cp v:nameU="idApplication" v:lbl="idApplication" v:type="0" v:sortKey="1" v:langID="1036" v:val="VT4(143)"/&gt;,我正在尝试获取属性。

例如: msg += "parent 6 previousSibling firstChild nextSibling v:nameU : " + evt.target.parentNode.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling.firstChild.nextSibling.getAttributeNS(null, 'v:nameU') + "\n\n";

但这不起作用。我试图在该行中添加一个 id,并且我可以获得 id 属性。但是对于现有的属性,它不起作用。

那么,为什么在 svg 结构中没有出现的每个节点之间都有文本兄弟?

为什么我无法访问我想要获取的属性?是不是因为它们来自 Visio (v:)

【问题讨论】:

    标签: javascript svg visio siblings


    【解决方案1】:

    我认为您正在寻找nextElementSiblingpreviousElementSibling

    TextNodes 是节点,文档中标签之间的空格可能是 TextNodes。

    var g=document.querySelector('#group327-2702');
    var cpElement = g.firstElementChild.firstElementChild.nextElementSibling;
    var r = cpElement.getAttributeNS(null, "v:nameu")+' '+
        cpElement.getAttributeNS(null, "v:lbl")+' '+
        cpElement.getAttributeNS(null, "v:type")+' '+
        cpElement.getAttributeNS(null, "v:sortkey")+' '+
        cpElement.getAttributeNS(null, "v:langid")+' '+
        cpElement.getAttributeNS(null, "v:val");
    
    document.querySelector('p').textContent= r;
    <svg><g id="group327-2702" transform="translate(1539.96,-1043.15)" v:mID="327" v:groupContext="group"><v:custProps>
                <v:cp v:nameU="idApplication" v:lbl="idApplication" v:type="0" v:sortKey="1" v:langID="1036" v:val="VT4(143)"/>
                <v:cp v:nameU="labelFR" v:lbl="labelFR" v:type="0" v:sortKey="3" v:langID="1036" v:val="VT4(Carnet d&#39;ordres)"/>
                <v:cp v:nameU="labelEN" v:lbl="labelEN" v:type="0" v:sortKey="4" v:langID="1036"
                        v:val="VT4(Order Management System )"/>
                <v:cp v:nameU="type" v:lbl="Type" v:type="0" v:langID="1036" v:val="VT4(Business)"/>
                <v:cp v:nameU="appLevel" v:lbl="appLevel" v:type="0" v:langID="1036" v:val="VT4(3)"/>
                <v:cp v:nameU="name" v:lbl="name" v:type="0" v:sortKey="2" v:langID="1036" v:val="VT4(MCE Trading)"/>
                <v:cp v:nameU="External" v:lbl="External" v:type="0" v:langID="1036" v:val="VT4(FALSE)"/>
                <v:cp v:nameU="_VisDM_type" v:lbl="type" v:langID="1036" v:val="VT4(Business)"/>
                <v:cp v:nameU="_VisDM_status" v:lbl="status" v:type="2" v:langID="1036" v:val="VT0(1):26"/>
            </v:custProps>
            <v:userDefs>
                <v:ud v:nameU="msvStructureType" v:prompt="" v:val="VT4(Container)"/>
                <v:ud v:nameU="msvSDContainerMargin" v:prompt="" v:val="VT0(0.078740157480315):24"/>
                <v:ud v:nameU="Label" v:prompt="" v:val="VT0(2):26"/>
                <v:ud v:nameU="ShapeVersion" v:prompt="" v:val="VT0(1):26"/>
                <v:ud v:nameU="LightColorText" v:prompt="" v:val="VT0(0):5"/>
            </v:userDefs>
            <title>Module.52.327</title>
            <g id="shape328-2703" v:mID="328" v:groupContext="shape">
                <title>Feuille.328</title>
                <v:userDefs>
                    <v:ud v:nameU="visVersion" v:val="VT0(14):26"/>
                </v:userDefs>
                <rect x="0" y="1652.6" width="93.5433" height="31.1811" rx="2.83465" ry="2.83465" class="st72"/>
            </g>
            <g id="shape327-2705" v:mID="327" v:groupContext="groupContent">
                <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/>
                <v:textRect cx="46.7717" cy="1668.19" width="93.55" height="31.1811"/>
                <text x="28.54" y="1661.89" class="st73" v:langID="1036"><v:paragraph v:horizAlign="1"/><v:tabList/>MCE Trading<v:newlineChar/><v:newlineChar/><tspan
                            x="7.63" dy="2.4em" class="st5">Order Management System </tspan> </text>            </g>
        </g></svg>
    
    <p id="log"></p>

    另外,由于您的问题,我发现了一件事情,请注意,您必须使用 getAttributeNS() 将您正在查看的属性小写

    【讨论】:

    • 嘿,谢谢!这就是我对文本节点的假设。但是,无论是否小写,getAttributeNS() 都不起作用。但是getAttribute 可以(情况相同)。所以我设法让它现在工作。我会发布答案。但是我不明白为什么我的 &lt;title&gt; 元素 hasChildNodes() 返回 true 因为我的 &lt;title&gt; 是空的并且 firstElementChild 是 null 。我猜,这是空文本节点。如果没有我手动处理的这种特殊情况,我需要一个hasChildElements 方法来做到这一点。
    • @Ellone,而不是hasChildNodes(),您可以检查element.chidren 的长度,如果它> 0,那么您的元素有子元素。关于getAttribute,我真的不明白,HTML属性不区分大小写而XML是......所以在我的理解中,它应该是相反的......
    • 谢谢,我会试试的。现在我正在尝试在光标图标位于与 idApplication 匹配的元素上方时更改光标图标,因此在我尝试添加的情况下:if (efc.getAttribute("v:nameU") == "idApplication") { efc.style.cursor = "help"; ... 但我猜我做错了。
    • 是的,您应该将样式应用于悬停的element,而不是您的efc
    • 这也不起作用。但实际上我认为这是因为我的 SVG 在不同的文件中。我使用 &lt;object&gt; 将它包含到我的 html 中,所以我不确定如何实现这一点。
    【解决方案2】:

    好的,所以我设法得到我想要做的属性如下,感谢Kaiido的帮助:

    var element = evt.target.parentNode;
        while (element) {
            if (element.children.length > 0) {
                var efc = element.firstElementChild;
                if (efc.hasAttribute("v:nameU")) {
                    if (efc.getAttribute("v:nameU") == "idApplication") {
                        element.style.cursor = "help";
                        var regExp = /\(([^)]+)\)/;
                        var appId = efc.getAttribute("v:val").match(regExp);
                        alert("id : " + appId[1]);
                        break;
                    }
                    else
                        element = element.previousElementSibling;
                }
                else
                    element = element.previousElementSibling;
            }
            else
                element = element.previousElementSibling;
        }
    }
    

    但是element.style.cursor = "help"; 这一行不起作用,光标图标在匹配 idApplication 的元素上保持不变。

    要知道的是,我的 svg 位于通过 &lt;object&gt; 标记包含在我的 html 中的不同文件中。

    【讨论】:

      猜你喜欢
      • 2019-08-14
      • 2012-03-27
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 2014-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多