Published
Edited
Mar 11, 2022
2 stars
Insert cell
Insert cell
chart = {
const ctx = DOM.context2d(width, height);
const squared = gridSize ** 2;
let xOffset = 0;

const draw = () => {
xOffset++;
// ctx.fillStyle = '#F5EDDF';
ctx.fillStyle = '#152828';
ctx.fillRect(0, 0, height, height); // clear canvas

for (let x = 0; x <= squared; x++) {
for (let y = 0; y <= squared; y++) {
ctx.save();
ctx.translate(
(xOffset + x * (gridSize * boxSize)) % height,
y * (gridSize * boxSize)
);
const fillNum = x - y; // number of boxes filled is the difference between both
const currentG = new Grid(fillNum, ctx);
ctx.restore();
}
}
};

draw();

yield ctx.canvas;
}
Insert cell
gridSize = 4
Insert cell
Insert cell
class Grid {
constructor(numFilled, ctx) {
ctx.fillStyle = 'white';
ctx.globalAlpha = 1 - Math.abs(numFilled) / (gridSize ** 2 + 2);
let colsToFil = Math.floor(Math.abs(numFilled) / gridSize); // full columns
let remainder = Math.abs(numFilled) % gridSize;
const isEvenCol = colsToFil % 2;
const gridHeight = boxSize * gridSize;

// FLIP HORIZONTALLY IF NEGATIVE (aka bottom left quadrant)
if (numFilled < 0) {
ctx.translate(gridHeight, 0);
ctx.scale(-1, 1);
}

// FILL SOLID COLUMNS
ctx.fillRect(0, 0, boxSize * colsToFil, gridHeight);
// FILL PARTIAL COLUMNS
if (remainder) {
ctx.fillRect(
colsToFil * boxSize, // x pos
isEvenCol ? 0 : gridHeight, // y pos
boxSize, // width
remainder * boxSize * (isEvenCol ? 1 : -1) // height
);
}

// stroke around each grid
ctx.fillStyle = 'transparent';
// ctx.strokeStyle = '#C3C7C6';
ctx.strokeStyle = '#152828';
ctx.strokeRect(0, 0, boxSize * gridSize, boxSize * gridSize);
}
}
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more