treemap = ({ layout, value, ...options } = {}) => ({
x1: 0,
x2: 1,
y1: 0,
y2: value,
x: options.z || options.fill || options.stroke,
y: value,
...options,
layout(index, scales, values, dimensions) {
const {
width,
marginLeft,
marginRight,
height,
marginTop,
marginBottom
} = dimensions;
const Z = values.x || values.z || values.fill || values.stroke || (() => 0);
const X1 = new Array();
const X2 = new Array();
const Y1 = new Array();
const Y2 = new Array();
const sizes = new Map();
for (const I of index) {
const root = d3.hierarchy({
children: d3
.rollup(
I,
(v) => ({ children: v }),
(i) => Z[i]
)
.values()
});
root.sum(
values.y2
? (i) => Math.abs(values.y2[i] - values.y1[i])
: (i) => Math.abs(values.y[i] - scales.y.scale(0))
);
sizes.set(I, root.value);
const tree = d3
.treemap()
.size([
width - marginLeft - marginRight,
height - marginTop - marginBottom
])(root);
for (const { x0, x1, y0, y1, data: i } of root.leaves()) {
X1[i] = x0;
X2[i] = x1;
Y1[i] = y0;
Y2[i] = y1;
}
}
const maxSize = d3.max(sizes.values());
for (const I of index) {
const r = Math.sqrt(sizes.get(I) / maxSize);
for (const i of I) {
X1[i] = X1[i] * r + marginLeft;
X2[i] = X2[i] * r + marginLeft;
Y1[i] = Y1[i] * r + marginTop;
Y2[i] = Y2[i] * r + marginTop;
}
}
values = {
...values,
x1: X1,
x2: X2,
y1: Y1,
y2: Y2,
x: mid(X1, X2),
y: mid(Y1, Y2)
};
return { index, values };
}
})