英文:
Why aren't g elements behaving as expected when D3 data is updated?
问题
I'm having trouble with D3's general update pattern not appending and updating as expected; I have provided 2 codepens that compare the binding of data using .data(data, d => d)
and .data(data, d => d[input])
, which is the only differing factor between the two - please refer to the codepens for a complete visual reference.
For context, the chart itself contains spin cycle class data per seat, sorted by ascending seat number. The DOM elements the data are bound to is structured as follows:
<svg>
> g.seat_0
>> rect.bar
>> text.measurement
> g.seat_1
>> rect.bar
>> text.measurement
.
.
.
> g.seat_n
>> rect.bar
>> text.measurement
</svg>
Each group represents a seat and contains a rect and text element. The initial data reads for d.total_power
, but the dropdown allows you to select a metric of interest corresponding to a key, with the updated value reflected in the width of the rect.bar
and text.measurement
upon selection.
Both do not behave as expected:
- In the case of (1)
data(d => d)
, the first bar itself is updated with the rest being entered and appended, which is the expected behaviour. - In the case of (2)
data(d => d[input])
, namely forTotal power
andTotal calories
options, there are a handful seats being entered and appended versus all transitioning to their updated value, which is the expected behaviour.
These issues aren't observed inAverage speed
orTotal distance
and selecting either in the dropdown demonstrates the expected behaviour of the chart.
You can refer to both the fill and the seat number appended on the lefthand side to narrow down the anomalies. Newly appended elements are filled with orange and updated elements are filled with red. I've also noticed it's the same seats that are acting up.
- For case (1), the very first seat.
- For case (2) in
d.total_power
seats 31, 43, 44, 47, 51;d.total_calories
seats 29, 35, 51.
Essentially my questions are:
- Why are some of these bars not behaving (appending + entering, updating) as expected? I went over the data and it looks consistent, so it isn't an issue with the object.
- I understand that
.data(d => d)
joins the entire object to the group. Why is it that when we join using this method do all elements are entered and appended on a new dropdown selection vs being updated when we specify the join using.data(d => d[input])
?
英文:
I'm having trouble with D3's general update pattern not appending and updating as expected; I have provided 2 codepens that compare the binding of data using .data(data, d => d)
and .data(data, d => d[input])
, which is the only differing factor between the two - please refer to the codepens for a complete visual reference.
For context, the chart itself contains spin cycle class data per seat, sorted by ascending seat number. The DOM elements the data are bound to is structured as follows:
<svg>
> g.seat_0
>> rect.bar
>> text.measurement
> g.seat_1
>> rect.bar
>> text.measurement
.
.
.
> g.seat_n
>> rect.bar
>> text.measurement
</svg>
Each group represents a seat and contains a rect and text element. The initial data reads for d.total_power
, but the dropdown allows you to select a metric of interest corresponding to a key, with the updated value reflected in the width of the rect.bar
and text.measurement
upon selection.
Both do not behave as expected:
- In the case of (1)
data(d => d)
, the first bar itself is updated with the rest being entered and appended, which is the expected behaviour. - In the case of (2)
data(d => d[input])
, namely forTotal power
andTotal calories
options, there are a handful seats being entered and appended versus all transitioning to their updated value, which is the expected behaviour.
These issues aren't observed inAverage speed
orTotal distance
and selecting either in the dropdown demonstrates the expected behaviour of the chart.
You can refer to both the fill and the seat number appended on the lefthand side to narrow down the anomolies. Newly appended elements are filled with orange and updated elements are filled with red. I've also noticed it's the same seats that are acting up.
- For case (1), the very first seat.
- For case (2) in
d.total_power
seats 31, 43, 44, 47, 51;d.total_calories
seats 29, 35, 51.
Essentially my questions are:
- Why are some of these bars not behaving (appending + entering, updating) as expected? I went over the data and it looks consistent, so it isn't an issue with the object.
- I understand that
.data(d => d)
joins the entire object to the group. Why is it that when we join using this method do all elements are entered and appended on a new dropdown selection vs being updated when we specify the join using.data(d => d[input])
?
答案1
得分: 1
这里的问题只是对于关键函数返回值的正确理解存在误解。以下是文档中的说明,我已经强调了关键部分:
可以指定关键函数来控制为每个数据分配给哪个元素,取代默认的按索引连接,方法是计算每个数据和元素的字符串标识符。
您需要返回一个字符串,一个唯一标识每个元素的字符串。
因此,让我们看看发生了什么:
- 当您使用
d => d
时,您将使用'[object Object]'
作为唯一标识符,这显然是错误的。 - 当您使用
d => d[input]
时,假设total_calories
,您将使用每个元素的总卡路里值作为它们的唯一标识符,显然这是不唯一的。
因此,由于每个条形图代表一个座位,正确的关键函数似乎只需这样:
.data(data, d => d.seat);
英文:
The problem here is just a misunderstanding regarding what's the correct returned value from a key function. Here's what the documentation says, emphasis mine:
> A key function may be specified to control which datum is assigned to which element, replacing the default join-by-index, by computing a string identifier for each datum and element.
You have to return a string, and a string which uniquely identifies each element.
That said, let's see what's happening:
- When you do
d => d
you're using'[object Object]'
as the unique identifier, which is obviously wrong. - When you do
d => d[input]
, let's saytotal_calories
, you're using the total calories value for each element as their unique identifier, and obviously that's not unique.
Therefore, as each bar represents a seat, the correct key function seems to be just this:
.data(data, d => d.seat);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论