我基于示例here在d3 v3中创建了一个森伯斯特。我无法理解在以下情况下attrTween()无法正常工作的原因。

path.transition()
  .duration(750)
  .attrTween("d", function(d) {
    var xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]),
        yd = d3.interpolate(y.domain(), [d.y, 1]),
        yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]);
    return function(d, i) {
      var p = i
          ? function(t) { return arc(d); }
          : function(t) { x.domain(xd(t)); y.domain(yd(t)).range(yr(t)); return arc(d); };
      return p
    };
  })


单击任意弧时出现以下错误。


  错误:属性d:预期的moveto路径命令(“ M”或“ m”),“函数(t){x…”。


但是,如下定义函数arcTween()并像这样调用.attrTween("d", arcTween(d))可以正常工作。

function arcTween(d) {
  var xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]),
      yd = d3.interpolate(y.domain(), [d.y, 1]),
      yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]);
  return function(d, i) {
    return i
        ? function(t) { return arc(d); }
        : function(t) { x.domain(xd(t)); y.domain(yd(t)).range(yr(t));return arc(d); };
 };
}

最佳答案

工作代码使用函数声明来定义function arcTween(d) { }。在.attrTween("d", arcTween(d))中使用此函数实际上将执行该函数,并从封闭函数d中传入参数click(d),这是绑定到用户单击的元素的数据。此调用用于捕获/关闭插值器dxdyd中的值yr,这些值又在返回的内部函数中使用。此返回的函数是由.attrTween()执行以返回用于过渡的插值器的函数。

在您的代码中,尝试内联函数声明时,您对上述外部函数的调用丢失了。因此,由于函数嵌套太深,您最终将获得无效的返回值。

但是,有一种简单的方法可以使您的代码正常工作:只需在内联函数后添加(d)即可执行该代码,就像执行以前的代码一样。

function click(d) {             // This d is what needs to be captured

  path.transition()
    .duration(750)
    .attrTween("d", function(d) {
      // var...                // This is where the outer d is closed over/captured
      return function(d, i) {  // This is another d not to be confused with the outer one
        // ...
      };
    }(d))                      // This will execute the function passing in click's d

}


请查看更新的Plunk以获取有效的演示。

10-06 04:18