我知道这里有一堆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
数据结构的变化如何破坏代码?
答案 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")
和其他类型的元素类似。