理解 D3 代码

Making sense of D3 code

我需要实现类似于 this 的东西,所以我试图理解这段代码。

有些事情我很难理解。例如,在下面的代码中,path.attr("d", linkArc); 似乎在调用 linkArc 函数。但是,linkArc 函数需要一个未传递的参数。它仍然设法获得一个名为 d 的对象。这是什么对象,它是如何通过的? path.attr中的d是什么意思?

// Use elliptical arc path segments to doubly-encode directionality.
function tick() {
    path.attr("d", linkArc); //<- this line
    circle.attr("transform", transform);
    text.attr("transform", transform);
}

function linkArc(d) {
  var dx = d.target.x - d.source.x,
      dy = d.target.y - d.source.y,
      dr = Math.sqrt(dx * dx + dy * dy);
  return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
}

有人能帮我理解一下吗?

这是 .attr() 运算符的工作方式:

引自 d3 文档 (https://github.com/mbostock/d3/wiki/Selections#attr):

selection.attr(name[, value])

If value is specified, sets the attribute with the specified name to the specified value on all selected elements. If value is a constant, then all elements are given the same attribute value; otherwise, if value is a function, then the function is evaluated for each selected element (in order), being passed the current datum d and the current index i, with the this context as the current DOM element. The function's return value is then used to set each element's attribute. A null value will remove the specified attribute.

基本上这意味着您可以像这样使用函数:

function linkArc(d, i) {
  // 'd' is the datum
  // 'i' is the index
  // 'this' will be the current DOM element
}

来自d3 docs

selection.attr(name[, value])

...if value is a function, then the function is evaluated for each selected element (in order), being passed the current datum d and the current index i, with the this context as the current DOM element. The function's return value is then used to set each element's attribute. A null value will remove the specified attribute...

这就是 d 的来源。这是当前设置的 selection 个对象 d (基准)。

如果您还将 i 添加到 linkArc() 函数,可以很好地说明这一点:

function linkArc(d,i) {
    console.log('d: ' + d + ' || i: ' + i);
    var dx = d.target.x - d.source.x,
        dy = d.target.y - d.source.y,
        dr = Math.sqrt(dx * dx + dy * dy);
    return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
}

还有一个Fiddle