{
const width = window.innerWidth * .9
const height = width * 2/3
const nrows = 10;
const ncols = 29;
const margin = {
top: 60,
bottom: 30,
left: 60,
right: 50
}
const gridWidth = width - margin.left - margin.right;
const gridHeight = height - margin.bottom - margin.top;
const svg = DOM.svg(
gridWidth + margin.left + margin.right,
gridHeight + margin.bottom + margin.top
)
const svgSel = d3.select(svg)
const sel = svgSel.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`)
svgSel.style('border', '1px solid black')
const cellWidth = gridWidth / ncols;
const cellHeight = gridHeight / nrows;
const gridXScale = d3.scaleLinear().domain([0, ncols]).range([0, gridWidth]);
const gridYScale = d3.scaleLinear().domain([0, nrows]).range([0, gridHeight]);
let data = []
for (let rowNumber = 0; rowNumber < nrows; rowNumber++) {
for (let colNumber = 0; colNumber < ncols; colNumber++) {
let obs = {
x: colNumber,
y: rowNumber,
height: cellHeight,
width: cellWidth
};
data.push(obs)
}
}
const join = sel.selectAll('g.grid')
.data(data)
.enter().append('g')
.attr('class', 'grid')
.attr('transform', (d, i) => {
return `translate(${gridXScale(d.x)}, ${gridYScale(d.y)})`
})
const circlePadding = 2
sel.selectAll('g.grid').each(function(d,i) {
const cell = d3.select(this).append('g')
cell.append('circle')
.attr('r', cellWidth / 2 - circlePadding)
.attr('fill', 'red')
});
return svg
}