{
const cols = 25;
const rows = 18;
const font = 40;
const maxDepth = 4;
const [cellWidth] = cm.measureText("森", { fontSize: font });
const width = cellWidth * cols;
const height = cellWidth * rows;
const chs = ["艹", "木", "林", "森"].reverse();
const degree = (x) => (x * 180) / Math.PI;
const x0 = (cols * cellWidth) / 2;
const x1 = rows * cellWidth - cellWidth / 2;
const scale = (d) => d * cellWidth;
const f = d3.scaleLinear([0, maxDepth], [font, 12]);
const tree = branch(0, 0, 6, 0, 0, maxDepth);
function branch(x, y, l, angle, depth, maxDepth) {
if (depth >= maxDepth) return;
const x1 = scale(x);
const y1 = scale(y);
const l1 = scale(l);
const data = d3.range(Math.round(l));
const textContent = chs[depth];
return cm.svg("g", {
transform: `translate(${x1}, ${y1}) rotate(${degree(angle)})`,
children: [
cm.svg("g", data, {
transform: (d) => `translate(${scale(d)}, 0) rotate(90)`,
children: [
(d, i) => cm.svg("text", { textContent, fontSize: f(depth) })
]
}),
branch(l, y, l * 0.8, Math.PI / 6, depth + 1, maxDepth),
branch(l, y, l * 0.8, -Math.PI / 6, depth + 1, maxDepth)
].filter((d) => d)
});
}
const app = cm.render({
width,
height,
draw: [
cm.svg("g", {
transform: `translate(${x0}, ${x1}) rotate(-90)`,
children: [tree]
})
]
});
invalidation.then(() => app.dispose());
return app.node();
}