Drawing a D3.js Grid
Drawing a Grid
grid.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script src="https://d3js.org/d3.v7.js"></script>
<script src="./js/grid.js"></script>
</head>
<body>
<div id="grid"></div>
<span id="data" style="display:none;">
[
[
{"x":1,"y":1,"width":100,"height":100,"selected":false},
{"x":101,"y":1,"width":250,"height":50,"selected":false}
],
[
{"x":101,"y":51,"width":100,"height":50,"selected":false},
{"x":201,"y":51,"width":150,"height":50,"selected":false}
],
[
{"x":1,"y":101,"width":50,"height":300,"selected":false},
{"x":51,"y":101,"width":50,"height":150,"selected":false},
{"x":101,"y":101,"width":100,"height":150,"selected":false},
{"x":201,"y":101,"width":150,"height":150,"selected":false}
],
[
{"x":51,"y":251,"width":50,"height":150,"selected":false},
{"x":101,"y":251,"width":100,"height":150,"selected":false},
{"x":201,"y":251,"width":150,"height":150,"selected":false}
]
]
</span>
</body>
</html>
./js/grid.js
document.addEventListener("DOMContentLoaded", function () {
// Deserialize the JSON string in the HTML.
const gridData = JSON.parse(document.querySelector("#data").textContent);
const grid = d3.select("#grid")
.append("svg")
.attr("width", "510px")
.attr("height", "510px");
const row = grid.selectAll()
.data(gridData)
.enter()
.append("g")
.attr("class", "row");
const noSelectedColor = "#ffffff";
const selectedColor = "#2C93E8";
const column = row.selectAll()
.data(d => {
return d;
})
.enter()
.append("rect")
.attr("class", "square")
.attr("x", function (d) {
return d.x;
})
.attr("y", function (d) {
return d.y;
})
.attr("width", function (d) {
return d.width;
})
.attr("height", function (d) {
return d.height;
})
.style("fill", noSelectedColor)
.style("stroke", "#222")
.on('click', function (d) {
d.selected = !d.selected;
let cell = d3.select(this);
if (d.selected) {
cell.style("fill", selectedColor);
} else {
cell.style("fill", noSelectedColor);
}
});
});
Code explanation
The code above is explained in order.
svg tag
const grid = d3.select("#grid")
.append("svg")
.attr("width", "510px")
.attr("height", "510px");
After execution, it changes as follows:
<div id="grid">
<svg width="510px" height="510px"></svg>
</div>
The selector used by the select method is the same as in JavaScript and CSS.
- The
svgtag is inserted into the retrievedd3.selectionobject with theappendmethod. - The tag is actually created by the
appendmethod. - The return value of the
appendmethod is ad3.selectionobject. - Attributes are added with the
attrmethod.
Assigning objects to the data method
const row = grid.selectAll()
.data(gridData)
.enter()
.append("g")
.attr("class", "row");
After execution, it changes as follows:
<div id="grid">
<svg width="510px" height="510px">
<g class="row"></g>
<g class="row"></g>
<g class="row"></g>
<g class="row"></g>
</svg>
</div>
- The grid objects are assigned with the
datamethod. - In this example, objects are created from a JSON string.
- Objects that could be assigned to the
datamethod are set on thed3.selectionobject with theentermethod. - The
append("g")method binds agelement to each array element of the object and creates tags.
Creating rect elements
const noSelectedColor = "#ffffff";
const selectedColor = "#2C93E8";
const gridStrokeColor = "#222222";
const column = row.selectAll()
.data(d => d)
.enter()
.append("rect")
.attr("class", "square")
.attr("x", d => d.x)
.attr("y", d => d.y)
.attr("width", d => d.width)
.attr("height", d => d.height)
.style("fill", noSelectedColor)
.style("stroke", gridStrokeColor)
.on('click', function (d) {
d.selected = !d.selected;
let cell = d3.select(this);
if (d.selected) {
cell.style("fill", selectedColor);
} else {
cell.style("fill", noSelectedColor);
}
});
After execution, it changes as follows:
<div id="grid">
<svg width="510px" height="510px">
<g class="row">
<rect class="square" x="1" y="1" width="100" height="100" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
<rect class="square" x="101" y="1" width="250" height="50" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
</g>
<g class="row">
<rect class="square" x="101" y="51" width="100" height="50" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
<rect class="square" x="201" y="51" width="150" height="50" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
</g>
<g class="row">
<rect class="square" x="1" y="101" width="50" height="300" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
<rect class="square" x="51" y="101" width="50" height="150" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
<rect class="square" x="101" y="101" width="100" height="150" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
<rect class="square" x="201" y="101" width="150" height="150" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
</g>
<g class="row">
<rect class="square" x="51" y="251" width="50" height="150" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
<rect class="square" x="101" y="251" width="100" height="150" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
<rect class="square" x="201" y="251" width="150" height="150" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
</g>
</svg>
</div>
- Here,
rectelements are created from the row object elements of the array previously bound to thegelements. x,y,width,height,fill, andstrokeare SVG attributes.- As with jQuery, events can be assigned with the
onmethod. - Here, a click event is assigned to toggle the background color.