Skip to main content
100%

TM

✓ Published0🌍 Public
Rrenenadorp
Last edited Aug 21, 2022
Created on Aug 21, 2022

This visualization presents a nested-rectangle chart built with D3 v6, where each fruit type (apple or lemon) is rendered as a group containing a circle, text label, and a variable number of stacked rectangles. The number of rectangles per group is determined by each fruit's "num" property, while their width scales according to the fruit type via a d3.scaleOrdinal color and radius scale. The example demonstrates a nested General Update Pattern, using `selection.each` to isolate each group’s DOM node and apply an independent data join, allowing rectangle counts and sizes to update dynamically as fruits are added, eaten, or replaced.

AI-generated description

A response to a question in the D3 Slack about different numbers of nested rectangles.

Original question by May Tan:

What i'm trying to do is add varying number of rectangles based on "num" in the data. The size of rectangle depends on the type of fruit. I realise that the rect size did update when the apple is changed into a lemon. However rect size didn't update on the last update when apple was eaten. My question is how do I write the selections when the data join is not based on number of array items, but range of some data. I am also sure i'm writing the update part wrongly as the size of rect did not get updated. Thanks for your help!

Answer:

Ahh I see what you mean. You want to essentially "break out" into a new update pattern, within each <g> element, so that each has its own unique data driven collection of rectangles. Here's a solution for it:

const groups = groupsEnter.merge(groupsUpdate);

groups.each(function (d) {
  const innerGroup = select(this);
  const rects = innerGroup
    .selectAll('rect')
    .data((d) => d3.range(d.num).map(() => d));

  rects
    .enter()
    .append('rect')
    .attr('height', '30px')
    .attr('stroke', 'black')
    .merge(rects)
    .attr('y', (d, i) => -40 * (i + 1))
    .attr('width', (d) => radiusScale(d.type));

  rects.exit().remove();
});

The trick is to use selection.each (and the old school function notation to access this) to isolate the DOM nodes for the groups (exposed by D3 as this), then use select to create a new D3 selection for each individual <g> element. With this in hand, we can have another nested but totally independent General Update Pattern, allowing us to make a different number of rectangles for each group.

MIT Licensed

Similar vizzes