d3中嵌套数据的节点错误类型的参数no

时间:2014-12-09 19:22:02

标签: javascript d3.js

我知道这里有一堆D3嵌套问题和答案,但我似乎无法弄清楚我的问题出在哪里。

当我第一次尝试嵌套时,我创造了以下要点:

http://bl.ocks.org/AndrewStaroscik/5686192。数据位于parentElement变量中:

var parentElement = [
  {name: "Path 1", startX: 25, startY: 75, segments: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]},
  {name: "Path 2", startX: 25, startY: 125, segments: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}
];

以下脚本按预期呈现一系列线段:

var g = svg.selectAll(".parent")
        .data(parentElement);

var gEnter = g.enter()
        .append("g")
        .attr("class", "parent")
        .attr('transform', function(d) { return 'translate(' + d.startX + ',' + d.startY + ')'; })
        .style('fill', 'none')
        .style('stroke', '#232323');

gEnter.selectAll(".child")
.data(function(d) { 
    console.log(d.segments);
    return d.segments; })
    .enter()
    .append("line")
    .attr('class', 'child')
    .attr('x1', function(d,i) { return lineLength * d; })
    .attr('y1', 0)
    .attr('x2', function(d,i) { return lineLength * (1 + d); })
    .attr('y2', 0);

现在我试图通过在嵌套中使用对象数组而不是数组来扩展它。我修改了数据如下:

var parentElement = [
{name: "Path 1", startX: 25, startY: 75, segments: [
    {type: "line", val: 1},
    {type: "line", val: 2},
    {type: "line", val: 3},
    {type: "line", val: 4},
    {type: "line", val: 5},
    {type: "line", val: 6},
    {type: "line", val: 7},
    {type: "line", val: 8},
    {type: "line", val: 9}
    ]},
{name: "Path 2", startX: 25, startY: 125, segments: [
    {type: "line", val: 1},
    {type: "line", val: 2},
    {type: "line", val: 3},
    {type: "line", val: 4},
    {type: "line", val: 5},
    {type: "line", val: 6},
    {type: "line", val: 7},
    {type: "line", val: 8},
    {type: "line", val: 9}
    ]},
];

selectAll子部分如下:

gEnter.selectAll(".child")
.data(function(d) { 
    console.dir(d.segments);
    return d.segments; })
    .enter()
    .append(function(d) { 
        console.log(d.type);
        return d.type; 
    })
    .attr('class', 'child')
    .attr('x1', function(d,i) { return lineLength * d.val; })
    .attr('y1', 0)
    .attr('x2', function(d,i) { return lineLength * (1 + d.val); })
    .attr('y2', 0);

最终目标是能够将不同类型的多个元素(圆形,正方形,路径等)添加到" g"元素使用相同的代码。所以

.append(function(d) { 
  console.log(d.type);
  return d.type; 
})
在这个例子中,

显然是不必要的,但最终会很重要。

以下是完整的无效版本:http://bl.ocks.org/AndrewStaroscik/e394056440e603374404

数据结构的变化如何破坏代码?

1 个答案:

答案 0 :(得分:1)

问题是.append()没有采用返回元素名称的函数 - 您必须将元素名称指定为字符串或从函数返回DOM元素。所以在你的情况下,这将是这样的:

.append(function(d) {
  return document.createElementNS(d3.ns.prefix.svg, d.type);
})

虽然这确实使它适用于您的情况,但这样做通常还需要您指定数据中的所有属性,因为不同类型的元素具有不同的属性。这可能会使您的代码和数据非常混乱,并在指定错误类型的数据时引入难以调试的错误。

坚持使用标准D3方法通常更容易,更安全。您可以通过在将数据传递给.data()之前过滤数据来实现相同的目的:

gEnter.selectAll("line.child")
  .data(function(d) {
    return d.segments.filter(function(e) { return e.type == "line"; });
  })
  .enter()
  .append("line")

和其他类型的元素类似。