Reputation: 745
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
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