7

使用 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 函数中设置断点表明了这一点a并且b始终未定义。进入 d3 代码,我看到当内部函数d3_selection_sortComparator使用适当的参数调用我的比较器时,除了它们与自己的未定义__data__成员进行与运算,这会导致undefined传入:

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

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

编辑:图片:

路径内容

参数 a 和 b 未定义

4

3 回答 3

5

selection.sort当它听起来像你期待的时候你正在使用Array.sort。该selection.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);
于 2014-10-04T13:29:33.253 回答
2

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

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

尝试这个:

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

这会将元素绑定到自身,您将能够在排序函数中引用它。

于 2014-10-08T12:08:04.467 回答
0

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

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

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

于 2012-08-03T09:34:18.357 回答