SVG howto select elements from use tag

Я использую SVG и javascript. Я хочу использовать «useэлемент» много, чтобы сохранить мой xml-файл маленьким.

Проблема в том, что я не могу найти способ изменить элементы, на которые useссылается тег. Пример см. В разделе мой код:

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<svg   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)?

Метки

1 ответ

  1. Нет простого способа сделать то, что вы хотите. Присущая природе defsuseэлементов и диктует, что субэлементами внутри исходного defsэлемента нельзя манипулировать индивидуально в useэлементах, полученных из него. Для этого потребуется, чтобы каждый useэлемент имел отдельную копию каждого подэлемента. Это разрушило бы одну из целей defsuseпартнерства, т. е. сохранить память.

    Однако, хотя нельзя изменить атрибуты одного конкретного подэлемента в useэлементе, можно изменить атрибуты всех подэлементов в useэлементе одновременно. (Достаточен ли такой грубый контроль, зависит от ваших конкретных потребностей.) Например, при копировании defsэлемента, содержащего несколько фигур, можно изменить цвет заливки всех фигур в одном конкретном useэлементе, изменив цвет заливки всего useэлемента. Это показано в фрагменте кода ниже путем изменения цвета заливки moused-over use element to red. Обратите внимание, однако, что это можно сделать только в том случае, если изменяемый атрибут не указан в исходном defsэлементе. Это показано в приведенном ниже фрагменте кода тем, что вы можете изменить на красный цвет цвет заливки кругов, окрашенных в зеленый цвет в useэлементах, но не тех, которые окрашены в зеленый цвет в defsэлементе.

    Один из способов сделать то, что, по-моему, вы хотите сделать, — это использовать клонирование. При наведении мыши на определенный useэлемент можно клонировать все, что требуется, из defsэлемента, поместить его поверх соответствующей формы в useэлементе, а затем изменить этот клонированный/повторно вставленный элемент, как вы хотите. Это показано в приведенном ниже фрагменте кода путем клонирования третьего круга каждый раз, когда вы наводите курсор мыши на useэлемент и помещаете его обратно в DOM, руководствуясь координатами use элемент. Я сделал это немного легче увидеть, слегка компенсируя клонированный элемент. Я также сделал так, чтобы он исчез, когда произойдет следующее событие наведения мыши, но хотите ли вы, чтобы это поведение зависело от вашей ситуации. (Обратите внимание, что размещение клонированного элемента в правильном положении может быть сложным в сложном документе, особенно когда есть группы внутри групп и были применены преобразования, например, масштабирование, вращения, переводы. В этих случаях вам, вероятно, потребуется использовать getCTM/ getScreenCTM.)

    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);
    }
    <svg   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>