Accessing a DOM object defined in an external SVG file

后端 未结 4 1054
天命终不由人
天命终不由人 2020-11-29 06:53

SVG standard allows to use and refer external SVG files.

I have a file circle.svg that defines a circle object with id \"the_circle\". From the main SVG

相关标签:
4条回答
  • 2020-11-29 07:30

    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

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

    <?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

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

    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:

    <?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>
    
    0 讨论(0)
  • 2020-11-29 07:32

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

      $.get '/assets/hexagon.svg', (svgFileData)->
        svgTag = svgFileData.documentElement
        $('body').append(svgTag)
        circle = $('#the_circle')
    
    0 讨论(0)
  • 2020-11-29 07:35

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

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

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

    0 讨论(0)
  • 2020-11-29 07:38

    You can access the necessary element a bit easier:

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

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

    0 讨论(0)
提交回复
热议问题