yavg
yavg

Reputation: 3051

How can I make a line between 2 elements dynamically (without knowing their coordinates)?

I have 2 elements, a circle and a rectangle. both are inside a different g element. As I am learning about d3.js I want that using the id selectors of each element, I can create a line that joins both elements. I don't know how to do it, I have read that with the property, getBoundingClientRect I can get the real properties of each element within the svg but i get errors when using it.

how can I do it?

var svg=d3.select("svg");
var g1=svg.append("g");
var g2=svg.append("g");

var rect=g1.append("rect").attr("id","myrect").attr("width",100).attr("height",100).attr("x",0).style("fill","blue");
var circle=g1.append("circle").attr("id","mycircle").attr("r",30).attr("cx",500).attr("cy",100).style("fill","red");

let origin= d3.select("#myrect");
let destiny= d3.select("#mycircle");
/*svg.append("line") 
  .style("stroke", "black") // colour the line
  .attr("x1", origin.x) // x position of the first end of the line
  .attr("y1", origin.y) // y position of the first end of the line
  .attr("x2", destiny.x) // x position of the second end of the line
  .attr("y2", destiny.y); // y position of the second end of the line
}*/
//.getBoundingClientRect()
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg style="width:1000px;height:500px; border:1px solid red;"></svg>

Upvotes: 3

Views: 66

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102194

There are better ways to do this, but here in this answer I'll just follow your approach.

In D3, methods such as attr() with just one argument are getters:

+origin.attr("x")

This will get the x attribute of the rectangle. The unary plus is important here because the getter returns a string, not a number. So, just get the rectangle's position, add half width/height, and get the circle's position:

var svg=d3.select("svg");
var g1=svg.append("g");
var g2=svg.append("g");

var rect=g1.append("rect").attr("id","myrect").attr("width",100).attr("height",100).attr("x",0).style("fill","blue");
var circle=g1.append("circle").attr("id","mycircle").attr("r",30).attr("cx",500).attr("cy",100).style("fill","red");

let origin= d3.select("#myrect");
let destiny= d3.select("#mycircle");
svg.append("line") 
  .style("stroke", "black") 
  .attr("x1", +origin.attr("x") + +origin.attr("width")/2) 
  .attr("y1", +origin.attr("y") + +origin.attr("height")/2) 
  .attr("x2", +destiny.attr("cx")) 
  .attr("y2", +destiny.attr("cy")); 
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg style="width:1000px;height:500px; border:1px solid red;"></svg>

Upvotes: 2

Related Questions