I'm trying to create a grid of squares using D3
. My code works, but I'd like to add some padding around each of the squares so that the grid does not look so "tight".
Here is my code:
class Matrix {
constructor(parentElement, data1, data2, data3) {
this.parentElement = parentElement;
this.data1 = data1;
this.data2 = data2;
this.data3 = data3;
this.cellHeight = 40;
this.cellWidth = 40;
this.initializeVisual()
}
initializeVisual() {
let vis = this;
vis.margin = {top: 20, right: 20, bottom: 20, left: 40};
vis.width = document.getElementById(vis.parentElement).getBoundingClientRect().width - vis.margin.left - vis.margin.right;
vis.height = 800 - vis.margin.top - vis.margin.bottom;
// init drawing area
vis.svg = d3.select('#' vis.parentElement).append('svg')
.attr('width', vis.width vis.margin.left vis.margin.right)
.attr('height', vis.height vis.margin.top vis.margin.bottom)
.append('g')
.attr('transform', `translate (${vis.margin.left}, ${vis.margin.top})`);
// Draws the initial grid
let squaresPerRow = 16
let scale = d3.scaleLinear()
.domain([0, squaresPerRow -1])
.range([0, this.cellWidth * squaresPerRow])
vis.squares = vis.svg.selectAll('.squares')
.data(d3.range(256))
.enter()
.append('rect')
.attr('x', (d, i) => {
let n = i % squaresPerRow
return scale(n)
})
.attr('y', (d, i) => {
let n = Math.floor(i / 16)
return scale(n)
})
.attr('width', this.cellWidth)
.attr('height', this.cellHeight)
.attr('fill', 'lightgrey');
}
The resulting grid looks like this:
How can I add the padding?
Thanks!
CodePudding user response:
Personally I'd change the linear scale for a point scale, but here's a solution using most of your code as it is.
First, get rid of that minus one in the domain, that's a cumbersome way for creating the padding:
.domain([0, squaresPerRow -1])
Then, after you set the padding (here named padding
), you can translate the x
and y
positions by half of it, and subtracting the rectangles' width and height by that padding.
Here's a demo, change the variable padding
for different spaces:
const svg = d3.select("div")
.append('svg')
.attr('width', 400)
.attr('height', 400);
let squaresPerRow = 8,
cellWidth = 40,
cellHeight = 40,
padding = 14;
let scale = d3.scaleLinear()
.domain([0, squaresPerRow])
.range([0, cellWidth * squaresPerRow])
const squares = svg.selectAll('.squares')
.data(d3.range(squaresPerRow ** 2))
.enter()
.append('rect')
.attr('x', (d, i) => {
let n = i % squaresPerRow
return scale(n) padding / 2
})
.attr('y', (d, i) => {
let n = Math.floor(i / squaresPerRow)
return scale(n) padding / 2
})
.attr('width', cellWidth - padding)
.attr('height', cellHeight - padding)
.attr('fill', 'lightgrey');
<script src="https://d3js.org/d3.v7.min.js"></script>
<div></div>