(Embed and) Refer to an external SVG via D3 and/or javascript

后端 未结 2 1905
轻奢々
轻奢々 2020-11-29 07:29

I have an .svg file and want to embed it in the svg strucure of my d3-graphic.

I also need to reference all paths/polygons attached to g-elements via an id of certai

相关标签:
2条回答
  • 2020-11-29 07:55

    There's a better solution.

    I hadn't realized that the d3.xml() function returns a read-in xml file as a document fragment (as opposed to converting it to JSON). In other words, it returns a ready-made DOM tree that can be inserted within you main document's DOM wherever you need it.

    Knowing that (and knowing that stand-alone SVG files are also XML files), this is likely the most reliable approach for adding external SVG content to your webpage:

    d3.xml("http://upload.wikimedia.org/wikipedia/commons/a/a0/Circle_-_black_simple.svg", 
            function(error, documentFragment) {
    
        if (error) {console.log(error); return;}
    
        var svgNode = documentFragment
                    .getElementsByTagName("svg")[0];
        //use plain Javascript to extract the node
    
        main_chart_svg.node().appendChild(svgNode);
        //d3's selection.node() returns the DOM node, so we
        //can use plain Javascript to append content
    
        var innerSVG = main_chart_svg.select("svg");
    
        innerSVG.transition().duration(1000).delay(1000)
              .select("circle")
              .attr("r", 100);
    
    });
    

    Fiddle here: http://jsfiddle.net/J8sp3/4/

    Notice in particular that (a) I am adding the content to an existing SVG, and (b) I am not deleting any of that SVG's current content.

    Of course, you can also add the SVG to a <div> or any other element that can contain it: http://jsfiddle.net/J8sp3/3/

    This method should work in any browser that supports SVG. I even tried it in IE8, and the DOM structure is correct even if IE8 doesn't know how to draw circles and rectangles!

    @Seb, please unselect the previous answer at pick this one as the accepted answer.

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

    The proper format for embedding SVG content from another file is to use a <use> element. However, you cannot then access the DOM structure (i.e., individual elements) of the nested SVG -- it's all treated as a single image.

    If you want to be able to modify the graphic described by the external file, you would be better off reading the external file as a text/XML file (using d3.text ), and then using that XML text to create the SVG graphic in the DOM by writing the content as the inner HTML of a container <div>

    d3.text("mySVGpicture.svg", function(error, externalSVGText) {
             if (error) {console.log(error); return;}
    
             chart_div.html(externalSVGText);
    
             svg = chart_div.select("svg");
    
             do_stuff();
    });
    

    Your DOM should now look like

    body
      div.chart
         svg
           g#anIDWhichIsInTheSVGFile
             g#DE
               path
               /*etc*/
           g#anotherIDWhichIsInTheSVGFile
    

    You can now select elements as normal, and set the position or size of the svg you created or remove g elements or whatever -- they are all just normal elements in your DOM. Make sure that your "id" attributes don't conflict -- they have to be unique for the entire page.

    Example here, showing additional content added to the SVG with d3, and a d3 transition selecting and modifying an element from the external SVG:
    http://jsfiddle.net/J8sp3/2/

    WARNING

    The original version of this answer suggested adding the external SVG content as a nested SVG inside the SVG that had already been created with D3.

    As Seb discovered, this method does not work on the latest Safari and Opera browsers, or on Chrome 31 and under.

    The problem is in the way the webkit browsers implement the innerHTML function, which is called by d3's selection.html() function. Specifically, the innerHTML function isn't implemented at all on SVG elements!

    What's most confusing is that the method doesn't return any errors, and some versions of Chrome actually display the SVG content without adding it to the DOM (as if you used <use xlink:href="external.svg"/>).

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