在D3.js中绘制多行
到目前为止,我一直在使用循环向D3可视化添加线条元素,但是这看起来并不符合API的精神。
比方说,我有一些数据,
var data = {time: 1, value: 2, value2: 5, value3: 3,value4: 2}, {time: 2, value: 4, value2: 9, value3: 2,value4: 4}, {time: 3, value: 8, value2:12, value3: 2,value4:15}]);
我想要四条线,时间是所有四条线的X轴。
我可以做这样的事情:
var l = d3.svg.line() .x(function(d){return xScale(d[keys[0]]);}) .y(function(d,i){ return yScale(d[keys[1]]);}) .interpolate("basis"); var l2 = d3.svg.line() .x(function(d){return xScale(d[keys[0]]);}) .y(function(d,i){ return yScale(d[keys[2]]);}) .interpolate("basis"); var l3 = d3.svg.line() .x(function(d){return xScale(d[keys[0]]);}) .y(function(d,i){ return yScale(d[keys[3]]);}) .interpolate("basis"); var l4 = d3.svg.line() .x(function(d){return xScale(d[keys[0]]);}) .y(function(d,i){ return yScale(d[keys[4]]);}) .interpolate("basis");
然后逐个添加(或循环)。
var line1 = group.selectAll("path.path1") .attr("d",l(data)); var line2 = group.selectAll("path.path2") .attr("d",l2(data)); var line3 = group.selectAll("path.path3") .attr("d",l3(data)); var line4 = group.selectAll("path.path4") .attr("d",l4(data));
有没有更好的更一般的方法来添加这些path?
是。 首先,我会重构您的数据,以便于迭代,如下所示:
var series = [ [{time: 1, value: 2}, {time: 2, value: 4}, {time: 3, value: 8}], [{time: 1, value: 5}, {time: 2, value: 9}, {time: 3, value: 12}], [{time: 1, value: 3}, {time: 2, value: 2}, {time: 3, value: 2}], [{time: 1, value: 2}, {time: 2, value: 4}, {time: 3, value: 15}] ];
现在你只需要一个通用的线路:
var line = d3.svg.line() .interpolate("basis") .x(function(d) { return x(d.time); }) .y(function(d) { return y(d.value); });
然后,您可以一次添加所有的path元素:
group.selectAll(".line") .data(series) .enter().append("path") .attr("class", "line") .attr("d", line);
如果要使数据结构格式更小,则还可以将时间提取到单独的数组中,然后使用二维数组作为值。 这看起来像这样:
var times = [1, 2, 3]; var values = [ [2, 4, 8], [5, 9, 12], [3, 2, 2], [2, 4, 15] ];
由于matrix不包含时间值,因此您需要从线条生成器的x存取器中查找它。 另一方面,y-accessor是简化的,因为你可以直接将matrix值传递给y-scale:
var line = d3.svg.line() .interpolate("basis") .x(function(d, i) { return x(times[i]); }) .y(y);
创build元素保持不变:
group.selectAll(".line") .data(values) .enter().append("path") .attr("class", "line") .attr("d", line);