{
const margin = {top: 10, right: 10, bottom: 10, left: 10};
const width = 960 - margin.left - margin.right;
const height = 600 - margin.top - margin.bottom;
d3.json("https://observablehq.com/@d3/treemap?@149")
.then(data => {
const root = d3.hierarchy(data)
.eachBefore(d => d.data.id = (d.parent ? d.parent.data.id + "." : "") + d.data.name)
.sum(d => d.value)
.sort((a, b) => b.height - a.height || b.value - a.value);
const treemap = d3.treemap()
.tile(d3.treemapResquarify)
.size([width, height])
.padding(1)
.round(true);
treemap(root);
const color = value => {
const hue = 120 - (value / 100) * 120;
return `hsl(${hue}, 70%, 50%)`;
};
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width + margin.left + margin.right, height + margin.top + margin.bottom])
.style("font", "10px sans-serif");
const leaf = svg.selectAll("g")
.data(root.leaves())
.join("g")
.attr("transform", d => `translate(${d.x0},${d.y0})`);
leaf.append("rect")
.attr("id", d => (d.leafUid = d.data.name + "-leaf-" + Math.random().toString().slice(2)))
.attr("class", "tile")
.attr("fill", d => { while (d.depth > 1) d = d.parent; return color(d.data.name); })
.attr("fill-opacity", 0.6)
.attr("width", d => d.x1 - d.x0)
.attr("height", d => d.y1 - d.y0)
.on("mousemove", function(d) {
const tooltip = d3.select(this.parentNode).select(".tooltip");
tooltip.style("display", "block");
tooltip.style("left", d3.event.pageX + 10 + "px");
tooltip.style("top", d3.event.pageY + 10 + "px");
})
.on("mouseout", function() {
const tooltip = d3.select(this.parentNode).select(".tooltip");
tooltip.style("display", "none");
});
leaf.append("clipPath")
.attr("id", d => (d.clipUid = d.data.name + "-clip-" + Math.random().toString().slice(2)))
.append("use")
.attr("xlink:href", d => "#" + d.leafUid);
leaf.append("text")
.attr("clip-path", d => d.clipUid)
.attr("font-size", d => Math.min((d.x1 - d.x0) / 5, 14))
.selectAll("tspan")
.data(d => d.data.name.split(/(?=[A-Z][^A-Z])/g))
.join("tspan")
.attr("x", 3)
.attr("y", (d, i, nodes) => `${(i === nodes.length - 1) * 0.3 + 1.2 +(d.y1 - d.y0) / 2}`)
.text(d => d);
leaf.append("foreignObject")
.attr("class", "tooltip")
.attr("width", "100")
.attr("height", "50")
.style("display", "none")
.append("xhtml:div")
.style("font-size", "12px")
.html(d => `${d.data.name}: ${d3.format(",")(d.value)}`);
return svg.node();
})
}