D3排序函数总是传递未定义的参数

时间:2012-08-02 16:18:09

标签: javascript svg d3.js

使用D3 2.4.2,我创建了许多路径元素,如下所示:

for (var i = 0; i < pathIndices.length; i++) {
  graph.append("svg:path")
    .style("stroke", colors[pathIndices[i]])
    .style("stroke-width", "2.5px")
    .style("fill", "none")
    .attr("class", PATH_CLASS)
    .attr("id", PATH_ID_PREFIX + pathIndices[i])
    .attr("d", lineFunc(data))[0];
}

他们都按预期绘制到屏幕上。稍后,当用户输入一些内容时,我想将其中一个带到前面,所以我有一个事件处理程序来执行此操作:

var pathToHighlight = selectPath(pathIndex);
var paths = d3.selectAll("." + PATH_CLASS);
paths.sort(
  function(a, b) {
    if (a === pathToHighlight) {
      return -1;
    }
    else if (b === pathToHighlight) {
      return 1;
    }
    else {
      return 0;
    }
  }
);

在Chrome中设置断点表示此处的路径选择成功(paths是一个SVGPathElements数组)。但是代码什么都不做,并且在sort函数中设置断点表明ab总是未定义的。进入d3代码,我看到当内部函数d3_selection_sortComparator使用适当的参数调用我的比较器时,除非它们与自己的未定义__data__成员进行AND运算,这会导致undefined传入:

// a and b are correct, but a.__data__ and b.__data__ are undefined
return comparator(a && a.__data__, b && b.__data__);

我在这里做错了什么?我的路径正确地绘制到屏幕上,所以看起来他们应该有正确的数据。正确?

编辑:图片:

Contents of path

parameters a and b are undefined

3 个答案:

答案 0 :(得分:5)

当您听起来像是期待selection.sort时,您正在使用Array.sortselection.sort方法用于根据绑定到元素ab数据对选择进行排序。如果您的元素没有绑定到它们的数据,那么这不会起作用。如果你想根据其他东西对选择进行排序(比如测试一个元素引用是否等于另一个),你应该在调用.sort()之前从选择中获取元素数组,如下所示:

// `paths` is a Selection
var paths = d3.selectAll("." + PATH_CLASS);
// `pathElements` is an Array
var pathElements = paths[0];

pathElements.sort(function(a,b) {
  // now `a` and `b` are Element references
  // ...
})

然后你必须采取额外的步骤,将DOM顺序与结果数组的顺序匹配。

那就是说,如果你只想把pathToHighlight带到前面,更好的方法是将这个单个元素重新附加到DOM。

如果选择pathToHighlight,您可以这样做:

var el = pathToHighlight.node();
el.parentNode.appendChild(el);

或者,如果它已经是Element引用,您可以这样做:

pathToHighlight.parentNode.appendChild(pathToHighlight);

答案 1 :(得分:2)

正如@jshanley所提到的,选择中的元素没有绑定到它们的任何数据(__data__属性未定义)。传递给selection.sort的函数将接收绑定到元素的数据,在您的情况下,它是未定义的。

您可以使用datum()函数将所选元素绑定到数据。

试试这个:

paths.datum(function () { return this };).sort(...)

这会将元素绑定到自身,您可以在sort函数中引用它。

答案 2 :(得分:0)

您可以尝试使用.datum()功能代替.__data__吗?

https://github.com/mbostock/d3/wiki/Selections#wiki-datum

  

selection.datum([值])
  获取或设置每个选定元素的绑定数据