Bubble chart

Bubble charts are non-hierarchical packed circles. The area of each circle is proportional its value (here, file size). The organic appearance of these diagrams can be intriguing, but also consider a treemap or a humble bar chart.

const width = 932;
const height = width;
const format = d3.format(",d");
const color = d3.scaleOrdinal(data.map((d) => d.group), d3.schemeObservable10);

const root = d3.pack()
    .size([width - 2, height - 2])
    .padding(3)
  (d3.hierarchy({children: data})
    .sum((d) => d.size));

const svg = d3.create("svg")
    .attr("viewBox", [0, 0, width, height])
    .attr("font-size", 10)
    .attr("font-family", "var(--sans-serif)")
    .attr("text-anchor", "middle");

const leaf = svg.selectAll("g")
  .data(root.leaves())
  .join("g")
    .attr("transform", (d) => `translate(${d.x + 1},${d.y + 1})`);

leaf.append("circle")
    .attr("id", (d) => (d.leafUid = DOM.uid("leaf")).id)
    .attr("r", (d) => d.r)
    .attr("fill-opacity", 0.7)
    .attr("fill", (d) => color(d.data.group));

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

leaf.append("text")
    .attr("clip-path", (d) => d.clipUid)
  .selectAll("tspan")
  .data((d) => d.data.name.split(/(?=[A-Z][a-z])|\s+/g))
  .join("tspan")
    .attr("x", 0)
    .attr("y", (d, i, nodes) => `${i - nodes.length / 2 + 0.8}em`)
    .text((d) => d);

leaf.append("title")
    .text((d) => `${d.data.title === undefined ? "" : `${d.data.title}
`}${format(d.value)}`);

display(svg.node());
const data = FileAttachment("data/flare.csv").csv()
  .then((data) => data.filter(({size}) => size !== ""))
  .then((data) => data.map(({name, size}) => ({name: name.split(".").pop(), title: name.replace(/\./g, "/"), group: name.split(".")[1], size: +size})))
  .then(display);
✎ Suggest changes to this page