Public
Edited
Nov 14, 2022
Insert cell
Insert cell
chart1 = {
const x = d3.scaleLinear().rangeRound([0, width]);
const y = d3.scaleLinear().rangeRound([0, height]);

const svg = d3
.create("svg")
.attr("viewBox", [0.5, -30.5, width, height + 30])
.style("font", "20px sans-serif");

let group = svg.append("g").call(render, treemap(data));
function render(group, root) {
const node = group
.selectAll("g")
.data(root.children.concat(root))
.join("g");

const tooltip = d3tip()
.style("background-color", "black")
.style("border-radius", "5px")
.style("padding", "10px")
.style("color", "white")
.attr("class", "tooltip")
.html(
(event, d) => `
<div style='float: right'>
dummy
</div>`
);
node.call(tooltip);
node
.filter((d) => (d === root ? d.parent : d.children))
.attr("cursor", "pointer")
.on("click", (event, d) => (d === root ? zoomout(root) : zoomin(d)))
.on("mouseover", tooltip.show)
.on("mouseleave", tooltip.hide);

node.append("title").text((d) => `${name(d)}`);
node
.append("rect")
.attr("id", (d) => (d.leafUid = DOM.uid("leaf")).id)
.attr("fill", (d) => (d === root ? "#ffc" : d.children ? "#00d" : "#ddd"))
.attr("stroke", "#fff");

node
.append("clipPath")
.attr("id", (d) => (d.clipUid = DOM.uid("clip")).id)
.append("use")
.attr("xlink:href", (d) => d.leafUid.href);

node
.append("text")

.attr("clip-path", (d) => d.clipUid)
.attr("font-weight", (d) => (d === root ? "bold" : null))
.selectAll("tspan")
.data((d) =>
(d === root ? name(d) : d.data.name)
.split(/(?=[^A-Z][[^a-z]])/g)
.concat(format(d.value))
)
.join("tspan")
// .attr("transform", function (d) {
// return "translate(" + d.x + "," + d.y + ")";
// })
.attr("x", 3)
.attr(
"y",
(d, i, nodes) => `${(i === nodes.length - 1) * 0.3 + 1.1 + i * 0.9}em`
)
// .attr("text-anchor", "middle")

.attr("fill-opacity", (d, i, nodes) =>
i === nodes.length - 1 ? 0.7 : null
)
.attr("font-weight", (d, i, nodes) =>
i === nodes.length - 1 ? "normal" : null
)
.text((d) => d);
group.call(position, root);
}

function position(group, root) {
group
.selectAll("g")
.attr("transform", (d) =>
d === root ? `translate(0,-30)` : `translate(${x(d.x0)},${y(d.y0)})`
)
.select("rect")
.attr("width", (d) => (d === root ? width : x(d.x1) - x(d.x0)))
.attr("height", (d) => (d === root ? 30 : y(d.y1) - y(d.y0)));
}

// When zooming in, draw the new nodes on top, and fade them in.
function zoomin(d) {
const group0 = group.attr("pointer-events", "none");
const group1 = (group = svg.append("g").call(render, d));

x.domain([d.x0, d.x1]);
y.domain([d.y0, d.y1]);

svg
.transition()
.duration(750)
.call((t) => group0.transition(t).remove().call(position, d.parent))
.call((t) =>
group1
.transition(t)
.attrTween("opacity", () => d3.interpolate(0, 1))
.call(position, d)
);
}

// When zooming out, draw the old nodes on top, and fade them out.
function zoomout(d) {
const group0 = group.attr("pointer-events", "none");
const group1 = (group = svg.insert("g", "*").call(render, d.parent));

x.domain([d.parent.x0, d.parent.x1]);
y.domain([d.parent.y0, d.parent.y1]);

svg
.transition()
.duration(750)
.call((t) =>
group0
.transition(t)
.remove()
.attrTween("opacity", () => d3.interpolate(1, 0))
.call(position, d)
)
.call((t) => group1.transition(t).call(position, d.parent));
}

return svg.node();
}
Insert cell
d3tip = require("d3-tip")
Insert cell
chart1.getElementsByTagName("title")
Insert cell
data = FileAttachment("pop@1.json").json()
Insert cell
treemap = data => d3.treemap()
.tile(tile)
(d3.hierarchy(data)
.sum(d => d.value)
.sort((a, b) => b.value - a.value))
Insert cell
Insert cell
function tile(node, x0, y0, x1, y1) {
d3.treemapBinary(node, 0, 0, width, height);
for (const child of node.children) {
child.x0 = x0 + child.x0 / width * (x1 - x0);
child.x1 = x0 + child.x1 / width * (x1 - x0);
child.y0 = y0 + child.y0 / height * (y1 - y0);
child.y1 = y0 + child.y1 / height * (y1 - y0);
}
}
Insert cell
name = d => d.ancestors().reverse().map(d => d.data.name).join("/")
Insert cell
width = 954
Insert cell
height = 524
Insert cell
format = d3.format(",d")
Insert cell
d3 = require("d3@6")
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