是否可以创建具有对象一致性的饼图?

Ste*_*ual 6 d3.js

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
}
Run Code Online (Sandbox Code Playgroud)

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

我创造了一个非常简单地展示这个问题的小提琴:

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

如果按"添加",它会向数组中添加一个随机int:这可以按预期工作.

如果按"删除",唯一转出的元素始终是进入饼图的最后一个元素.简而言之,它的行为就像一个LIFO堆栈.预期的行为是相关的饼弧转换出来.

是否可以将对象一致性应用于馅饼?我也试过添加一个关键功能(没有在小提琴上演示),但这只是打破(奇怪的是,它与我的堆叠图形工作正常).

谢谢.

mbo*_*ock 11

解决这个问题的最简单方法是缺失值设为零,而不是完全删除它们,在第三部分中的饼图更新一系列的例子.然后,您可以免费获得对象的持久性:在更新中,您具有相同数量的元素,顺序相同.

另外,如果你想有一个数据连接在第四部分,你必须告诉D3在进入弧应该从进入,并在退出的弧线应该退出来.一个合理的策略是从相反的数据中找到最接近的相邻弧:对于给定的进入弧,找到旧数据中最近的相邻弧(转换前); 同样,对于给定的退出弧,在新数据中找到最接近的相邻弧(转换后).

继续这个例子,假设您正在显示不同地区的苹果销售,并希望切换到显示橙子.您可以使用以下键函数来维护对象的恒定性:

function key(d) {
  return d.data.region;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

在索引中的每个进入弧i(其中ddata1[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!
  }
}
Run Code Online (Sandbox Code Playgroud)

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

总而言之,这是第五部分:

饼图更新v