Public
Edited
Apr 2
Insert cell
Insert cell
Insert cell
{
regenerate;

const size = 640;
const padding = 5;
const rows = 8;
const unit = (size - padding * 2) / rows;
const cells = fillSquares(rows);
const pos = (x) => padding + x * unit;
const pick = (a) => a[d3.randomInt(a.length)()];

const app = cm.app({
width: size,
height: size,
styleBackground: "#fff5eb",
renderer: cm.rough(),
draw: [
cm.svg("path", cells, {
transform: (d) => `translate(${pos(d.x)}, ${pos(d.y)})`,
fill: () => pick(colors),
fillStyle: () => pick(styles),
stroke: "black",
strokeWidth: 2,
fillWeight: 2,
d: (d) => pick(symbols)(5, 5, (d.x1 - d.x) * unit - 10)
})
]
});

return app.render();
}
Insert cell
function fillSquares(rows) {
const cells = [{ x: 0, y: 0, x1: rows, y1: rows }];

fill(0);

function fill(i) {
const cell = cells[i];
const point = pick(cell);
const subcells = divide(cell, point).filter(defined);
cells.splice(i, 1, ...subcells);
for (let j = subcells.length - 1; j >= 0; j--) {
if (!square(subcells[j])) fill(i + j);
}
}

function divide(cell, point) {
const { x, y, x1, y1 } = cell;
const [px, py] = point;
return [
{ x, y, x1: px, y1: py },
{ x: px, y, x1: x1, y1: py },
{ x: px, y: py, x1, y1 },
{ x: x, y: py, x1: px, y1: y1 }
];
}

function defined({ x, y, x1, y1 }) {
return x1 - x >= 1 && y1 - y >= 1;
}

// Don't just generate one big blank square!!!
function square({ x, y, x1, y1 }) {
return x1 - x === y1 - y && x1 - x !== rows;
}

function pick(cell) {
const { x, y, x1, y1 } = cell;
const points = d3
.cross(d3.range(x, x1 + 1), d3.range(y, y1 + 1))
.filter((point) => divide(cell, point).some(square));
return points[d3.randomInt(points.length)()];
}

return cells;
}
Insert cell
symbols = [
cm.symbolCircle,
cm.symbolDiamond,
cm.symbolSquare,
cm.symbolX
]
Insert cell
colors = [
"#CA6A6F",
"#8B9D83",
"#DAC474",
"#8DA9B0",
"#ADA9A5",
"#DF8749",
"#A791A3"
]
Insert cell
styles = [
"hachure",
"solid",
"zigzag",
"cross-hatch",
"dots",
"dashed",
"zigzag-line"
]
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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