将选择与组合并

时间:2018-09-25 13:00:30

标签: d3.js merge

我已经为使用新的选择合并制定了一致的模式,这对于数据和/或比例可能会更改的可重用图表非常有用。

我也一直在成功使用键功能。

但是,当输入并添加具有多个元素的组时,似乎出现问题。数据已在组中成功更新,但未成功附加元素。

我已经通过添加修复程序来解决这个问题(请参见下文),但是我确定确实很明显,需要对其进行更改以解决它。

有什么想法吗?

//define data group 
var my_group = svg.selectAll(".data_group")
                  .data(my_data,function(d){return d.id});

//enter new groups
var enter = my_group.enter()
                    .append("g")
                    .attr("class","data_group");

//append items to group
enter.append("text").attr("class","group_item group_text")
enter.append("circle").attr("class","group_item group_circle");

//merge and remove
my_group.merge(enter);
my_group.exit().remove();

//fix added to reset changing data for bars.
d3.selectAll(".group_item").each(function(d){
  d3.select(this)._groups[0][0].__data__ = d3.select(this)._groups[0][0].parentElement.__data__;
});

d3.selectAll(".group_text")
  .... add properties to text - ie x,y,fill,text-anchor,text 

d3.selectAll(".group_circle")
     .... add properties to circle - ie cx,cy,fill,stroke,radius

2 个答案:

答案 0 :(得分:1)

绝对不需要选择父组,获取其数据并将其重新绑定到子元素,就像您的问题和其他答案中的代码一样。这是向后弯曲。另外,请勿按照建议删除/重新添加元素,这不是惯用的D3方法。

事情很简单:新数据存在于“输入”选择中的子元素中。您只需要使用父母的选择(与select()一起传播它们即可。

这是使用(大部分)代码的基本演示。该代码生成1到5个数据对象,并具有一个称为someProperty的随机属性。您会看到,使用each(),仅更改了“ enter”选择中的子元素:

var svg = d3.select("svg");
d3.interval(function() {
  var data = d3.range(1 + ~~(Math.random() * 4)).map(function(d) {
    return {
      id: "id" + d,
      "someProperty": ~~(Math.random() * 100)
    }
  });
  update(data);
}, 2000);

function update(my_data) {
  var my_group = svg.selectAll(".data_group")
    .data(my_data, function(d) {
      return d.id
    });

  my_group.exit().remove();

  var enter = my_group.enter()
    .append("g")
    .attr("class", "data_group");

  enter.append("text").attr("class", "group_item group_text")
  enter.append("circle").attr("class", "group_item group_circle");

  my_group = my_group.merge(enter);


  console.log("---")

  d3.selectAll(".group_text").each(function(d) {
    console.log(JSON.stringify(d))
  });
}
.as-console-wrapper { max-height: 100% !important;}
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>

现在,如果我们使用您父母的选择...

my_group.select(".group_text").each(function(d) {
    console.log(d)
})

...您会看到所有属性已更新:

var svg = d3.select("svg");
d3.interval(function() {
  var data = d3.range(1 + ~~(Math.random() * 4)).map(function(d) {
    return {
      id: "id" + d,
      "someProperty": ~~(Math.random() * 100)
    }
  });
  update(data);
}, 2000);

function update(my_data) {
  var my_group = svg.selectAll(".data_group")
    .data(my_data, function(d) {
      return d.id
    });

  my_group.exit().remove();

  var enter = my_group.enter()
    .append("g")
    .attr("class", "data_group");

  enter.append("text").attr("class", "group_item group_text")
  enter.append("circle").attr("class", "group_item group_circle");

  my_group = my_group.merge(enter);


  console.log("---")

  my_group.select(".group_text").each(function(d) {
    console.log(d)
  })
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>

最后,在您现在删除的答案中,您正在使用my_group.selectAll()。问题是selectAll()不会传播数据。

看看我做的这张桌子:

+------------------+----------------------------------+----------------------------+
| Method           |              select()            |         selectAll()        |
+------------------+----------------------------------+----------------------------+
| Selection        | selects the first element        | selects all elements that  |
|                  | that matches the selector string | match the selector string  |
+------------------+----------------------------------+----------------------------+
| Grouping         | Does not affect grouping         | Affects grouping           |
+------------------+----------------------------------+----------------------------+
| Data propagation | Propagates data                  | Doesn't propagate data     |
+------------------+----------------------------------+----------------------------+

请注意传播数据不会传播数据

答案 1 :(得分:0)

复制绑定到父g元素的数据的更多d3方法

无需添加修复程序

d3.selectAll(".group_text")
    .datum(function () { return d3.select(this.parentNode).datum(); } )
    //   .... add properties to text - ie x,y,fill,text-anchor,text 

d3.selectAll(".group_circle")
    .datum(function () { return d3.select(this.parentNode).datum(); } )
    //   .... add properties to circle - ie cx,cy,fill,stroke,radius