【问题标题】:D3 - Retrieve data associated with a clicked element in the chartD3 - 检索与图表中单击的元素关联的数据
【发布时间】:2021-02-21 18:47:22
【问题描述】:

我有一个使用 D3 正确构建的堆积条形图。 原始数据如下所示:

var originalData = {
            
header: ["label", "count", "missing"],
rows:   [
            {label: "A", count: 0, missing: 0},
            {label: "B", count: 24, missing: 59},
            {label: "C", count: 6, missing: 77},
            {label: "D", count: 7, missing: 76},
            {label: "E", count: 2, missing: 81},
            {label: "F", count: 7, missing: 76},    
            {label: "G", count: 0, missing: 83}
        ]
};

因此,每个条形图都是一堆条形图,分别代表 countmissing 数量。 这个originalData 被传递给d3.stack 函数以生成用于绘制矩形的堆叠条形对象。

var barChartObject = d3.stack().keys(originalData.header.slice(1) )
                                  .value( (d,key) => d[key] )
                                  (originalData.rows);

生成的对象是这样的:

[
    [[0,0],[0,24],[0,6],[0,7],[0,2],[0,7],[0,0]]
    [[0,0],[24,83],[6,83],[7,83],[2,83],[7,83],[0,83]]
]

注意:每个“对”实际上是一个对象,其中包含用于构建对的原始数据,这些数据在 .data 字段中可用。

绘制矩形的代码如下所示:

onBarClick = (event, data) => {

    ...    
}

var barGroupTag = this.svg.selectAll()
                       .data(barChartObject)
                       .enter()
                       .append("g")

barGroupTag.selectAll("rect")
        .data(d => d)
        .enter()
        .append("rect")
        ...
        .on("mouseover", this.onMouseOverBar)
        .on("mouseout", this.onMouseOutBar)
        .on('click', this.onBarClick);

然后使用<g>标签手动包装矩形以允许自定义属性存储。

 barGroupTag.selectAll("rect")
            .each( function () {
                       
                       var rectNode = this;
             
                       d3.select(rectNode.parentNode)
                         .insert("g")
                         .append( () => rectNode); 
                   }
                 ); 

问题是我需要访问与每个柱关联的原始数据,但不幸的是,在回调中,第二个参数返回整个堆栈而不是单个对。所以我无法弄清楚被点击的这个数组的元素是什么。我检查了传递给回调的第三个参数,但事实并非如此。例如,如果我单击 [0,24] 元素(第二个堆栈的底部栏),在回调中我得到 event 作为 PointerEvent 对象,而 data 是对象数组:

[[0,0],[0,24],[0,6],[0,7],[0,2],[0,7],[0,0]]

我可以使用.data 字段来访问原始数据,例如data[index].data.labeldata[index].data.count,但问题是我不知道索引的值

这很奇怪,因为如果我使用 .attr 向矩形添加一个属性,则会收到单个对象(d 值)而不是整个数组,因此我可以执行以下操作:

.attr("xxx", d => {return d.data.count > 0 ? "aaa" : "bbb" } )

那么为什么传递给回调的值是整个 bar 数组,而不是与单击 bar 关联的单个元素?如何获取与点击栏关联的原始数据?

【问题讨论】:

  • 您使用的是 d3 v6,对吗?当我转到this example 并将.on("click", console.log) 添加到条形图时,我看到正在记录各个值。在左下栏的情况下,我看到[0, 5038433]
  • 是的,版本是6.2.0d3-collection 是版本1.0.7。我在 Observable 上的另一个样本上注意到了同样的行为。样品工作正常,但不是我的。关于您链接的示例,我发现 d3.stack 函数的使用方式有所不同。此外,使用d3.stack 的输出时,选择也略有不同。我会尝试做出一些改变。
  • 我忘了提到 <rect> 节点是用 <g> 标记手动包装的(请参阅更新的代码)。这就是问题所在。此操作正在更改与rect 关联的数据。删除该代码后,onclick 回调报告了正确的对值。
  • 很好,现在解决了吗?
  • 如果这解决了您的问题,我建议您写一个自我回答,或者最好完全删除该帖子,因为对我们其他人来说没有什么可取的。

标签: javascript d3.js bar-chart


【解决方案1】:

问题是由barGroupTag.selectAll("rect").each(...) 语句引起的,我在其中手动将每个rect 包装为g 标记。由于未知原因,此操作还更改了与每个矩形关联的数据。删除该代码后,onclick 回调报告了正确的配对数据对象。

所以要小心selectAll("xxx").each(...) 语句,特别是如果您正在修改 DOM 对象的结构或层次结构并且您在此类对象上定义了事件回调。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多