moe
moe

Reputation: 745

How to draw a rectangle in D3.js with only 2 coordinates

I am learning D3.js and will use it to draw simple lines and rectangles. My problem is, I am using data that is meant for RPG. So for a rectangle RPG only needs 2 points and it will use that diagonal line to complete the rectangle. I don't have a height or width just 2 coordinates. Is there a way to draw a rectangle in D3 using only 2 points?

Upvotes: 2

Views: 11614

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102219

Since you have two points (coordinates), the task is simple:

For the x and y position, use the first point. For the width and height of the rectangle, just calculate x2 - x1 and y2 - y1, respectively.

Here is a demo with three rectangles. In the data array, each object has 4 properties, corresponding to the two points (this is just an example, you may change the code according to your data structure):

var svg = d3.select("body")
	.append("svg")
	.attr("width", 400)
	.attr("height", 200);
	
var data = [{x1: 20, x2: 60, y1: 30, y2: 50},
{x1: 50, x2: 80, y1: 100, y2: 150},
{x1: 200, x2: 400, y1: 10, y2: 100}];

var rects = svg.selectAll("foo")
	.data(data)
	.enter()
	.append("rect")
	.attr("x", d=> d.x1)
	.attr("y", d=> d.y1)
	.attr("width", d=> d.x2 - d.x1)
	.attr("height", d=> d.y2 - d.y1)
	.attr("fill", "teal");
<script src="https://d3js.org/d3.v4.min.js"></script>

Here is the same principle, but with the data containing two arrays, the first array being the first point and the second array being the second point:

var svg = d3.select("body")
	.append("svg")
	.attr("width", 400)
	.attr("height", 200);
	
var data = [[[20,30],[40,50]], [[50,100],[80,150]], [[200,30],[400,100]]];

var rects = svg.selectAll("foo")
	.data(data)
	.enter()
	.append("rect")
	.attr("x", d=> d[0][0])
	.attr("y", d=> d[0][1])
	.attr("width", d=> d[1][0] - d[0][0])
	.attr("height", d=> d[1][1] - d[0][1])
	.attr("fill", "teal");
<script src="https://d3js.org/d3.v4.min.js"></script>

For both the above snippets to work, the data has to have the coordinates in this sequence: first the top-left point, then the bottom-right point. Of course, you can write a function to check this and swap the points if the order is not correct.

For drawing a diagonal, just choose the points you want. For instance, from the top-left to the bottom-right:

var svg = d3.select("body")
	.append("svg")
	.attr("width", 400)
	.attr("height", 200);
	
var data = [{x1: 20, x2: 60, y1: 30, y2: 50},
{x1: 50, x2: 80, y1: 100, y2: 150},
{x1: 200, x2: 400, y1: 10, y2: 100}];

var rects = svg.selectAll("foo")
	.data(data)
	.enter()
	.append("rect")
	.attr("x", d=> d.x1)
	.attr("y", d=> d.y1)
	.attr("width", d=> d.x2 - d.x1)
	.attr("height", d=> d.y2 - d.y1)
	.attr("fill", "teal")
	.attr("opacity", 0.3);
  
var lines = svg.selectAll("foo")
	.data(data)
	.enter()
	.append("line")
	.attr("x1", d=> d.x1)
	.attr("y1", d=> d.y1)
	.attr("x2", d=> d.x2)
	.attr("y2", d=> d.y2)
	.attr("stroke", "firebrick")
	.attr("stroke-width", 2);
<script src="https://d3js.org/d3.v4.min.js"></script>

Upvotes: 7

Related Questions