6

bl.ocks 网站上的饼图更新示例不会“就地”更新元素:

http://bl.ocks.org/j0hnsmith/5591116

function change() {
  clearTimeout(timeout);
  path = path.data(pie(dataset[this.value])); // update the data
  // set the start and end angles to Math.PI * 2 so we can transition
  // anticlockwise to the actual values later
  path.enter().append("path")
      .attr("fill", function (d, i) {
        return color(i);
      })
      .attr("d", arc(enterAntiClockwise))
      .each(function (d) {
        this._current = {
          data: d.data,
          value: d.value,
          startAngle: enterAntiClockwise.startAngle,
          endAngle: enterAntiClockwise.endAngle
        };
      }); // store the initial values

  path.exit()
      .transition()
      .duration(750)
      .attrTween('d', arcTweenOut)
      .remove() // now remove the exiting arcs

  path.transition().duration(750).attrTween("d", arcTween); // redraw the arcs
}

相反,它只是将新的值数组视为全新的数据,并相应地调整图表的大小。

我创建了一个小提琴非常简单地演示了这个问题:

http://jsfiddle.net/u9GBq/23/

如果您按“添加”,它会向数组添加一个随机整数:这按预期工作。

如果您按“删除”,则唯一被转换出的元素始终是最后一个进入饼图的元素。简而言之,它的行为类似于 LIFO 堆栈。预期的行为是让相关的饼弧转出。

是否可以将对象一致性应用于馅饼?我也尝试过添加一个关键功能(未在小提琴上演示),但这只是中断(奇怪的是它适用于我的堆叠图)。

谢谢你。

4

2 回答 2

11

此问题的最简单解决方案是将缺失值设置为零,而不是像饼图更新系列示例的第三部分中那样完全删除它们。然后你就可以免费获得对象的恒常性:你有相同数量的元素,以相同的顺序,跨越更新。

或者,如果您想要像第 IV 部分中那样进行数据连接,您必须告诉 D3 进入的弧应该从哪里进入,以及退出的弧应该从哪里退出。一个合理的策略是从相反的数据中找到最近的相邻弧:对于给定的进入弧,在旧数据中找到最近的相邻弧(过渡前);同样对于给定的退出弧,在新数据中找到最近的相邻弧(转换后)。

继续该示例,假设您正在显示不同地区的苹果销量,并且想要切换到显示橙子。您可以使用以下关键功能来维护对象的恒定性:

function key(d) {
  return d.data.region;
}

(这假设您正在使用d3.layout.pie,它包装您的原始数据并将其公开为d.data。)

现在说当你过渡到橙子时,你有以下旧数据和新数据:

var data0 = path.data(), // retrieve the old data
    data1 = pie(region.values); // compute the new data

对于索引处的每个输入弧i(其中dis data1[i]),您可以依次遍历 中的先前数据data1,并查看是否可以在 中找到匹配项data0

var m = data0.length;
while (--i >= 0) {
  var k = key(data1[i]);
  for (var j = 0; j < m; ++j) {
    if (key(data0[j]) === k) return data0[j]; // a match!
  }
}

如果找到匹配项,您输入的弧线可以从匹配弧线的结束角度开始。如果您没有找到前面的匹配项,则可以寻找后面的匹配弧。如果没有匹配项,则两个数据集之间没有重叠,因此您可以从角度 0° 输入弧线,或者进行交叉淡入淡出。您同样可以将此技术应用于退出弧。

综上所述,这是第五部分

饼图更新 v

于 2013-05-31T00:11:32.850 回答
0

好的,找到了解决方案。诀窍是以这种方式传递密钥:

path = path.data(pie(dataset), function (d) {return d.data}); // this is good

而不是不通过它,或者以错误的方式通过它:

path = path.data(pie(dataset, function (d) {return d.data})); // this is bad

这是一个更新的小提琴,在正确的弧线上有一个工作过渡!:)

http://jsfiddle.net/StephanTual/PA7WD/1/

于 2013-05-31T00:05:05.537 回答