javascript 访问在外部 SVG 文件中定义的 DOM 对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3346106/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 00:54:36  来源:igfitidea点击:

Accessing a DOM object defined in an external SVG file

javascriptdomsvg

提问by rodrigob

SVG standard allows to use and refer external SVG files.

SVG 标准允许使用和引用外部 SVG 文件。

I have a file circle.svgthat defines a circle object with id "the_circle". From the main SVG file I am able to include this circle and animate it, using SVG linking.

我有一个文件circle.svg,它定义了一个 ID 为“the_circle”的圆对象。从主 SVG 文件中,我可以使用SVG linking包含这个圆圈并为其设置动画。

I would also like to access the same circle object via javascript, how can I do this ? What is the javascript equivalent of xlink:href="url(#the_image)#the_circle"?

我还想通过 javascript 访问同一个圆对象,我该怎么做?什么是 javascript 等价物xlink:href="url(#the_image)#the_circle"

Using document.getElementById('the_image')I can only access the SVGImageElement but not the objects defined inside the included SVG.

使用document.getElementById('the_image')I 只能访问 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>

回答by jbeard4

It seems like the "right" way to do this would actually be to use an SVG "use" element, rather than an image. The reason for this is that the DOM interface of the SVG use element specifies a property "instanceRoot", which allows you to get the root of the "instance tree" corresponding to that use element: http://www.w3.org/TR/SVG/struct.html#InterfaceSVGUseElement

看起来这样做的“正确”方法实际上是使用SVG“使用”元素,而不是图像。原因是SVG use 元素的DOM 接口指定了一个属性“instanceRoot”,可以让你获取到那个use 元素对应的“实例树”的根:http: //www.w3.org/ TR/SVG/struct.html#InterfaceSVGUseElement

So, you would end up with a solution that looks something like the following: circle.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="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>

Document which uses the svg root node of circle.svg:

使用 circle.svg 的 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>

Unfortunately, though, while Firefox supports use of the use element with external documents, there's currently a bug in Webkit which does not allow this: https://bugs.webkit.org/show_bug.cgi?id=12499

不幸的是,虽然 Firefox 支持在外部文档中使用 use 元素,但目前 Webkit 中存在一个不允许这样做的错误:https://bugs.webkit.org/show_bug.cgi?id =12499

Also, Firefox does not seem to implement the instanceRoot property for use elements.

此外,Firefox 似乎没有为 use 元素实现 instanceRoot 属性。

So, it seems you may need to work around the limitations of current SVG implementations. The way I would recommend doing this is to use XMLHttpRequest to download the document to which you would like to link, and import the DOM of the downloaded document into your host document's DOM. The following code implements this, and works in Firefox, Opera and Chromium:

因此,您似乎需要解决当前 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>

回答by Spadar Shut

You can access the necessary element a bit easier:

您可以更轻松地访问必要的元素:

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

See this imagefor reference (taken on dev.opera.com) enter image description here

请参阅 此图像以供参考(取自dev.opera.com在此处输入图片说明

回答by martyn

Here's a solution to this problem when using React and ES6. Usage:

这是在使用 React 和 ES6 时解决此问题的方法。用法:

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

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

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

回答by Duke

To supplement @echo-flow's excellent solution with the code in jQuery/Coffeescript:

用 jQuery/Coffeescript 中的代码补充@echo-flow 的优秀解决方案:

  $.get '/assets/hexagon.svg', (svgFileData)->
    svgTag = svgFileData.documentElement
    $('body').append(svgTag)
    circle = $('#the_circle')