4

我想从这样的嵌套对象结构中绘制多条 svg 线(使用 D3.js):

data = [ 
{ Name: "jim", color: "blue", Points: [{x:0, y:5 }, {x:25, y:7 }, {x:50, y:13}] },
{ Name: "bob", color: "green", Points: [{x:0, y:10}, {x:25, y:30}, {x:50, y:60}] }
];

var line_gen = d3.svg.line().interpolate("linear")
                .x(function(d){return d.x;})
                .y(function(d){return d.y;}); 

基于这个问题,我的第一次尝试是使用 svg:g 表示第一个嵌套级别,然后访问组内的第二个嵌套级别以呈现线条:

var g = svg.selectAll(".linegroup")
.data(data).enter()
.append("g")
.attr("class", "linegroup")
.style("stroke", function(d) { return d.color; })
.style("fill", "none");

g.selectAll(".line")
.data(function(d) { return d.Points;})
.enter().append("svg:path")
  .attr("d", line_gen);

但这并没有渲染任何线条。相反,在每个组中,我为三个数据点中的每一个都获得了一个空路径标签。显然,数据的形状正在引起问题。

<g class="linegroup" style="stroke: #0000ff; fill: none;">
    <path></path>
    <path></path>
    <path></path>
</g>

我确实找到了一个不使用组的解决方案(将作为答案发布),但我仍然想知道为什么组解决方案不起作用。

4

2 回答 2

2

这是一个答案,主要基于这个问题,除了它不使用 d3.entries:

data = [ 
{ Name: "jim", color: "blue", Points: [{x:0, y:5 }, {x:25, y:7 }, {x:50, y:13}] },
{ Name: "bob", color: "green", Points: [{x:0, y:10}, {x:25, y:30}, {x:50, y:60}] }
];

svg = d3.select("body").append("svg:svg").attr("width", 100).attr("height", 100)

var line_gen = d3.svg.line().interpolate("linear")
                .x(function(d){return d.x;})
                .y(function(d){return d.y;});

svg.selectAll(".line")
  .data(data)
  .enter().append("svg:path")
    .attr("d", function(d) { return line_gen(d.Points); })   // <<<
    .style("stroke", function(d) { return d.color; })
    .style("fill", "none");

这里的关键方法是不将 line_gen 函数直接返回到“d”属性,而是将其包装在另一个函数中,该函数从外部对象传递正确的嵌套数组。

另请参阅关于 d3.entries 与 d3.values的精彩讨论。d3.entries 似乎针对类似问题提出了很多建议,但我认为这对我的情况并没有帮助。

于 2013-01-28T16:46:14.417 回答
1

原因是您想为列表中的每个元素画一条线——嵌套选择适用于存在更多级别的情况。例如,如果您有一个以列表为元素的列表,并且每个列表元素都包含一组路径(例如,对曲线集进行分组),则嵌套选择将是合适的。

在您的情况下发生的事情是 d3 正在为每个元素生成一条新路径Points- 也就是说,每个点都有一条。

于 2013-01-28T16:47:13.347 回答