首页 > 解决方案 > 在 d3.js 中使用两级嵌套数据绘制图形符号

问题描述

我正在尝试复制这个带点的多线图示例。我的数据基本上是相同的,我在第一级有一个具有名称和值的对象,然后在第二级有几个值,即内部值。values 内部数组的长度为 40。

现在,一个要求是所有路径的所有点都在 DOM 内的同一个 g 组内。这给我带来了很多麻烦,因为我似乎无法弄清楚如何将circles与嵌套数据的适当部分连接起来。

我试过的最后一件事是:

 var symbolsb = d3.select("#plot-b") // plot-b is the graph area group within the svg
    .append("g")
    .attr("id", "symbols-b");
    
  symbolsb.selectAll("circle")
    .data(games, function(d) {console.log(d.values) // games is my data object
            return d.values})
    .enter()
    .append("circle")
    .attr("class", "symbolsb")
    .attr("cx", function(d,i) {console.log(d)
            return x(d.values.date);})
    .attr("cy", function(d,i) {return y_count(d.count);})
    .attr("r", function(d,i) { 
      let parent = this.parentNode;
      let datum = d3.select(parent).datum();
      console.log(parent)
      if (i%3 === 1 && included_names.includes(datum[i].name)) {
        return 8;}
      else {return null;}})
    .style("fill", function(d,i) { 
      let parent = this.parentNode;
      let datum = d3.select(parent).datum();
        {return color(datum.name);}});

当我(错误地)理解该data()函数时,我认为通过返回、、 和d.values中的函数只会看到里面的数组,但是当登录到函数中的控制台以定义、等时,我看到了再次完整的对象。同样,我虽然我应该只得到对象的一部分。cxcyrd.valuesdcxcygamesvalues

我已经能够通过加载数据并g在定义时附加 a 来获得一个看起来像我想要的结果的图symbolsb,但这会为每组圆圈创建一个组。

我认为问题来自于我对data()函数如何访问嵌套对象的困惑。因此,任何帮助解释这一点将不胜感激。

标签: javascriptd3.jsnested-object

解决方案


如果您可以提供实时复制,例如在ObservableVizHub笔记本中,那就太好了。

这条线看起来很可疑

.data(games, function(d) {console.log(d.values) // games is my data object
            return d.values})

第二个参数*selection*.data应该是一个“键函数”,一个为每个数据返回一个唯一字符串标识符的函数。在这里,您提供了一个对象 ( d.values),它将[object Object为每个数据点字符串化为 ]。这也解释了为什么您在games记录时会看到完整的对象。我认为在这里删除第二个参数是安全的.data()

.data(games)

这看起来也不对

.attr("r", function(d,i) { 
  let parent = this.parentNode;
  let datum = d3.select(parent).datum();
  console.log(parent)
  if (i%3 === 1 && included_names.includes(datum[i].name)) {
    return 8;}
  else {
    return null;
*emphasized text*}})

我不完全确定您要在这里做什么。如果您尝试访问数据点的名称,您可以使用.attr("r", function(d,i) { if (included_names.includes(d.name)) { return 8 } else { return 0} )


推荐阅读