2014-10-10 69 views
1

我已经有了从JSON有效载荷生成的多折线折线图的基本演示。它按预期工作,但我觉得我没有充分利用D3库来正确解析或绑定数据。来自JSON的D3 Multiseries折线图

什么是嵌套数据的最佳格式?例如,对象的对象,数组的数组等?

http://jsfiddle.net/thinkin3d/nc2sgmcz/

的JSON有效载荷看起来是这样的:

var data = { 
    "Series 1": { 
     "20141020": 3.5003987252672744, 
     "20141019": 2.505802351020492, 
     "20141018": 1.511804171940014}, 
    "Series 2": { 
     "20141008": 3.386547593121662, 
     "20141009": 2.1369256424188166, 
     "20141010": 0.88701610875722286}, 
    "Series 3": { 
     "20141024": 1.041445076319178, 
     "20141025": 1.1241181263211502, 
     "20141026": 1.38667149365412} 
} 

我打电话d3.entries将其改造成一个数组:

var entries = d3.entries(data); 

然后我再打电话d3.entries ,每次我想要访问第二级中的特定键值对时:

var entry = d3.entries(d.value); 

我多次调用并重复自己,这就是为什么我觉得必须有更好的方式,我不知道。

我没有使用D3库的哪些部分?

理想情况下,我希望能够保持JSON有效载荷格式,但如果在交付之前进行简单的重新排列操作,D3会使事情变得容易许多,我全都是耳朵!

代码:

var margin = {top: 20, right: 20, bottom: 30, left: 50}, 
     width = 600 - margin.left - margin.right, 
     height = 400 - margin.top - margin.bottom; 

var parseDate = d3.time.format("%Y%m%d").parse; 

var x = d3.time.scale() 
     .range([0, width]); 

var y = d3.scale.linear() 
     .range([0, height]); 

var color = d3.scale.category20(); 

var xAxis = d3.svg.axis() 
     .scale(x) 
     .orient("bottom"); 

var yAxis = d3.svg.axis() 
     .scale(y) 
     .orient("left"); 

var area = d3.svg.area() 
     .interpolate("basis") 
     .x(function (d) { 
      return x(parseDate(d.key)); 
     }) 
     .y0(height) 
     .y1(function (d) { 
      return y(d.value); 
     }); 

var svg = d3.select("body").append("svg") 
     .attr("width", width + margin.left + margin.right) 
     .attr("height", height + margin.top + margin.bottom) 
     .append("g") 
     .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

var entries = d3.entries(data); 

color.domain(entries.map(function (d) { 
    return d; 
})); 

var minX = d3.min(entries, function (kv) { 
    var entry = d3.entries(kv.value); 
    return d3.min(entry, function (d) { 
     return parseDate(d.key); 
    }) 
}); 
var maxX = d3.max(entries, function (kv) { 
    var entry = d3.entries(kv.value); 
    return d3.max(entry, function (d) { 
     return parseDate(d.key); 
    }) 
}); 
var minY = d3.min(entries, function (kv) { 
    var entry = d3.entries(kv.value); 
    return d3.min(entry, function (d) { 
     return d.value; 
    }) 
}); 
var maxY = d3.max(entries, function (kv) { 
    var entry = d3.entries(kv.value); 
    return d3.max(entry, function (d) { 
     return d.value; 
    }) 
}); 

x.domain([minX, maxX]); 
y.domain([minY, maxY]); 

var element = svg.selectAll(".element") 
     .data(entries) 
     .enter().append("g") 
     .attr("class", "element"); 

element.append("path") 
     .attr("class", "area") 
     .attr("d", function (d) { 
      var entry = d3.entries(d.value); 
      return area(entry); 
     }) 
     .style("fill", function (d) { 
      return color(d.key); 
     }); 

element.append("text") 
     .datum(function (d) { 
      var entry = d3.entries(d.value); 
      return { 
       name: d.key, 
       date: parseDate(entry[entry.length - 1].key), 
       value: entry[entry.length - 1].value 
      }; 
     }) 
     .attr("transform", function (d) { 
      return "translate(" + x(d.date) + "," + y(d.value) + ")"; 
     }) 
     .attr("x", -6) 
     .attr("dy", ".35em") 
     .text(function (d) { 
      return d.name; 
     }); 

svg.append("g") 
     .attr("class", "x axis") 
     .attr("transform", "translate(0," + height + ")") 
     .call(xAxis); 

svg.append("g") 
     .attr("class", "y axis") 
     .call(yAxis); 
+0

fddle it。更好,更好。 – 2014-10-10 15:46:25

+0

http://jsfiddle.net/thinkin3d/nc2sgmcz/ – 2014-10-19 10:44:41

回答

0

您可以简化代码相当,如果你第一次得到所有x和y的值,然后这些阵列的程度。这是相对简单的,唯一要注意的是,你需要拼合嵌套数组:

var allX = d3.values(data).map(d3.keys) 
    .reduce(function(a,b) { return a.concat(b); }).map(parseDate); 
var allY = d3.values(data).map(d3.values) 
    .reduce(function(a,b) { return a.concat(b); }); 

x.domain(d3.extent(allX)); 
y.domain(d3.extent(allY)); 

这从您的初始数据结构得到的值,并为每个无论是键或值,这取决于你是否希望的x或y。然后使用.reduce()将此嵌套数组展平。对于y,我们完成了,对于x,日期被解析。然后,您可以直接使用d3.extend()来获取域的值。

完整演示here