SVG如何从use标签中选择元素

时间:2016-05-02 18:10:02

标签: svg

我使用SVG和javascript。我想大量使用'use元素来保持我的xml文件很小。

问题是我无法找到更改use标记引用的元素的方法。请参阅我的代码示例:

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:lang="en" onload="init()" width="1000" height="900">

    <defs>

        <g id="test">
            <circle cx="10" cy="20" r="20" fill="green" />
            <line x1="10" y1="10" x2="100" y2="60" stroke="red" />
        </g>

    </defs>

    <use xlink:href="#test" x="10" y="10" />
    <use xlink:href="#test" x="50" y="50" />


    <script type="text/javascript">
        <![CDATA[

        function init()
        {
            var allUses = document.querySelectorAll('[*|href="#test"]');
            for (i = 0; i < allUses.length; i++) {
                allUses[i].addEventListener('mouseover', testOver, false);
            }
        }

        function testOver()
        {
            // on mouse over the element I want the circle the mouse goes over to change color to blue and the line to purple
            // how to get a handle to the circle ???
            //this.[get circle?]
        }

        function attribute(element, name, value)
        {
        element.setAttribute(name, value);
        }

        ]]>
    </script>

</svg>

如何获取use元素内部元素的句柄(基于每个'use tag')?

1 个答案:

答案 0 :(得分:0)

没有简单的方法可以做你想做的事。 defsuse元素的固有特性决定了原始defs元素中的子元素无法在从它派生的use元素中单独操作。为此,需要每个use元素具有每个子元素的单独副本。这将破坏defs / use伙伴关系的其中一个目的,即节省内存。

但是,虽然您无法更改use元素中某个特定子元素的属性,但您可以更改子所有的属性 - 一次use元素中的元素。 (这种粗略控制是否足够取决于您的特定需求。)例如,复制其中包含多个形状的defs元素时,您可以更改所有形状的填充颜色通过更改整个use元素的填充颜色,在一个特定的use元素中。这通过将moused-over use元素的填充颜色更改为红色显示在下面的代码段中。但请注意,只有当您要更改的属性在原始defs元素中指定而不是时才能执行此操作。下面的代码片段中显示了这样一个事实:您可以将use元素中绿色圆圈的填充颜色更改为红色,而不是defs元素中绿色的绿色。

实现我认为你想做的事情的一种方法是使用克隆。当您将鼠标悬停在特定use元素上时,可以从defs元素中克隆任何内容,将其放在use元素中相应形状的顶部,然后更改该元素克隆/重新插入元素,但你想要的。每次将鼠标悬停在use元素上并将其放回由use元素的坐标引导的DOM中时,通过克隆第三个圆圈,可以在下面的代码片段中显示这一点。通过略微抵消克隆元素,我更容易看到这一点。当下一次鼠标悬停事件发生时,我也让它消失了,但是你是否想要这种行为取决于你的情况。 (请注意,将克隆元素放置在正确的位置在复杂文档中可能会非常棘手,特别是当组内有组并且已应用变换时,例如缩放,旋转,翻译。在这些情况下,您可能需要使用getCTM / getScreenCTM。)

&#13;
&#13;
function init() {
  var allUses = document.querySelectorAll('[*|href="#test"]');
  for (i = 0; i < allUses.length; i++) {
    allUses[i].addEventListener('mouseover', testOver, false);
  }
}

function testOver() {
  attribute(this, "fill", "red");
  var circle3 = document.querySelector("defs").querySelector(".circle3").cloneNode(true);
  var highlighted = document.querySelector("#highlighted");
  highlighted.replaceChild(circle3, highlighted.childNodes[0]);
  attribute(circle3, "fill", "blue");
  var x = parseFloat(this.getAttribute("x")) + 4;
  var y = parseFloat(this.getAttribute("y")) + 4;
  attribute(circle3, "transform", "translate(" + x + "," + y + ")");
}

function attribute(element, name, value) {
  element.setAttribute(name, value);
}
&#13;
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:lang="en" onload="init()" width="450" height="150">

  <defs>
    <g id="test">
      <circle class="circle1" cx="10"  cy="20" r="20" fill="green" />
      <circle class="circle2" cx="50"  cy="20" r="20" />
      <circle class="circle3" cx="90"  cy="20" r="20" />
      <circle class="circle4" cx="130" cy="20" r="20" />
    </g>
  </defs>

  <use class="five" xlink:href="#test" x="10" y="10" fill="green" />
  <use class="five" xlink:href="#test" x="50" y="80" fill="green" />

  <g id="highlighted">
    <g id="dummyElementToBeReplaced">
    </g>
  </g>

</svg>
&#13;
&#13;
&#13;