Search code examples
javascriptd3.jssvgxmlhttprequestes6-promise

Selecting element in external SVG


I'm trying to select and modify specific parts of an SVG via D3.js. The SVG is external. I don't know whether to import the SVG via tags or using d3.xml. Neither is working for me.

I managed to get the SVG in the HTML via tags but I still can't select any of the elements within the SVG using d3.

I also do not know if best practice is to use use tags or d3.xml

https://jsfiddle.net/67fvhwc0/

d3.xml("https://upload.wikimedia.org/wikipedia/commons/8/89/Baseball_diamond_clean.svg").mimeType("image/svg+xml").get(function(error, xml) {
  if (error) throw error;
  document.body.appendChild(xml.documentElement);
});

var base = d3.select('#rect2801');
console.log(base);
base.attr("fill", "red");

Solution

  • You have a simple error here: you're using D3 v5, not v4. Because of that, you have to use promises (instead of XMLHttpRequest in v4).

    Therefore, it should be:

    d3.xml("https://upload.wikimedia.org/wikipedia/commons/8/89/Baseball_diamond_clean.svg")
        .then(function(xml) {
            document.body.appendChild(xml.documentElement);
        });
    

    Also, move everything that depends on the data to inside Promise.prototype.then(), or to the adequate function. So:

    d3.xml("https://upload.wikimedia.org/wikipedia/commons/8/89/Baseball_diamond_clean.svg")
        .then(function(xml) {
            document.body.appendChild(xml.documentElement);
            var base = d3.select('#rect2801');
            console.log(base);
        });
    

    To read more about the changes in D3 v5: https://github.com/d3/d3/blob/master/CHANGES.md

    Here is your working code:

    d3.xml("https://upload.wikimedia.org/wikipedia/commons/8/89/Baseball_diamond_clean.svg").then(function(xml) {
      document.body.appendChild(xml.documentElement);
      var base = d3.select('#rect2801');
      base.style("fill", "red")
    });
    <script src="https://d3js.org/d3.v5.min.js"></script>

    PS: We cannot console.log D3 selections in the stack snippet, it freezes. Instead of that, I'm turning the base red.

    PPS: Don't use <object>. You'll find out that's complicated using D3 selectors on that SVG.