Home > Software engineering >  Append new shapes to existing shapes within SVG document D3
Append new shapes to existing shapes within SVG document D3

Time:06-15

In D3 I'm used to creating visuals from a blank div. However I'm trying to get my head around the following.

I have an svg document (https://raw.githubusercontent.com/gangrel11/samplefiles/main/d3 task1.svg) which is just 3 rectangles.

What I'm trying to do is append 3 new shapes (circles) to each one of the existing rectangles so that they appear in the centre of each one.

This is where I got to:

const svgUrl = "https://raw.githubusercontent.com/gangrel11/samplefiles/main/d3 task1.svg"
d3.xml(svgUrl).then(render);


function render(svg) {

  // add svg
  d3.select("body").node().append(svg.documentElement)
  
  var svg = d3.select("body").append("svg");

      svg.selectAll("rect")
      .append("rect")
      .attr("width", 20)
      .attr("height", 20)
      .attr("x", 20)
      .attr("y", 10)
      .attr("fill",  "red")
      
      }

Here is my jsfiddle

CodePudding user response:

You have a few problems:

  1. You are adding another svg element instead of using the existing one. My suggestion is changing:

d3.select("body").append("svg");

to

d3.select("body").select("svg #layer1");

  • notice that I also targeted the g element #layer1 that get transformed.
  1. you try to append rect element to rect element but svg doesn't know how to draw rect inside rect - this syntax is invalid. instead, you can target each element and use his position using the .each method and append them after all the existing rects.

code: function render(svg) {

  // add svg
  d3.select("body").node().append(svg.documentElement)
  
  var svg = d3.select("body").select("svg #layer1");

  svg.selectAll("rect")
      .each(function (rect){
         const {x, y} = this.getBoundingClientRect();
         svg.append("rect")
            .attr("width", 20)
            .attr("height", 20)
            .attr("x", this.getAttribute('x'))
            .attr("y", this.getAttribute('y'))
            .attr("fill",  "red");
      
  }); 
}
  • Related