Доступ к объекту DOM, определенному во внешнем файле SVG - PullRequest
12 голосов
/ 27 июля 2010

Стандарт SVG позволяет использовать и ссылаться на внешние файлы SVG.

У меня есть файл circle.svg, который определяет объект круга с идентификатором "the_circle".Из основного SVG-файла я могу включить этот круг и анимировать его, используя SVG-ссылку .

. Я также хотел бы получить доступ к тому же объекту круга через JavaScript, как я могу это сделать??Что такое javascript-эквивалент xlink:href="url(#the_image)#the_circle"?

Использование document.getElementById('the_image') Я могу получить доступ только к SVGImageElement, но не к объектам, определенным внутри включенного SVG.

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >

  <image 
    id="the_image"
    x="0" y="0"  width="100%" height="100%"
    xlink:href="circle.svg" />

  <animateTransform     
    xlink:href="url(#the_image)#the_circle"

    attributeName="transform" attributeType="XML"
    type="translate" 
    from="0" to="25"
    dur="1s" repeatCount="indefinite" 
    additive="replace" fill="freeze" />
</svg>

Ответы [ 4 ]

13 голосов
/ 31 июля 2010

Кажется, что «правильный» способ сделать это на самом деле - использовать SVG-элемент «use», а не изображение. Причина этого заключается в том, что интерфейс DOM элемента использования SVG определяет свойство «instanceRoot», которое позволяет получить корень «дерева экземпляров», соответствующего этому элементу использования: http://www.w3.org/TR/SVG/struct.html#InterfaceSVGUseElement

Итак, вы получите решение, которое выглядит примерно так: circle.svg:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="4in" height="4in" id="the_svg"
     viewBox="0 0 4 4" version="1.1"
     xmlns="http://www.w3.org/2000/svg">
    <circle r="1" fill="blue" stroke="none" id="the_circle"/>
</svg>

Документ, который использует корневой узел svg circle.svg:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" id="foo"
     version="1.1"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink"> 

    <use xlink:href="circle.svg#the_svg"/>
</svg>

К сожалению, хотя Firefox поддерживает использование элемента use с внешними документами, в настоящее время в Webkit есть ошибка, которая не позволяет этого: https://bugs.webkit.org/show_bug.cgi?id=12499

Кроме того, Firefox, похоже, не реализует свойство instanceRoot для используемых элементов.

Так что, возможно, вам придется обойти ограничения текущих реализаций SVG. Я бы порекомендовал сделать это, используя XMLHttpRequest, чтобы загрузить документ, на который вы хотели бы связать, и импортировать DOM загруженного документа в DOM вашего основного документа. Следующий код реализует это и работает в Firefox, Opera и Chromium:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" id="foo"
     version="1.1"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink"> 

    <script>
    function fetchXML  (url, callback) {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', url, true);
        xhr.onreadystatechange = function (evt) {
        //Do not explicitly handle errors, those should be
        //visible via console output in the browser.
        if (xhr.readyState === 4) {
            callback(xhr.responseXML);
        }
        };
        xhr.send(null);
    };

    //fetch the document
    fetchXML("http://localhost:8082/tmp/circle.svg",function(newSVGDoc){
        //import it into the current DOM
        var n = document.importNode(newSVGDoc.documentElement,true);
        document.documentElement.appendChild(n);

        var circle = document.getElementById("the_circle"); //now you have the circle
    }) 
    </script>
</svg>
11 голосов
/ 19 августа 2011

Вы можете получить доступ к нужному элементу немного проще:

document.getElementById('the_image').contentDocument.getElementById('the_circle')

См. это изображение для справки (взято на dev.opera.com ) enter image description here

1 голос
/ 16 октября 2015

Вот решение этой проблемы при использовании React и ES6. Использование:

<SvgImage url='pathToImage.svg'></SvgImage>

https://gist.github.com/mikkel/8b79a713ff06bbec379d

1 голос
/ 19 августа 2011

Дополнить отличное решение @ echo-flow кодом из jQuery / Coffeescript:

  $.get '/assets/hexagon.svg', (svgFileData)->
    svgTag = svgFileData.documentElement
    $('body').append(svgTag)
    circle = $('#the_circle')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...