简体   繁体   English

在nvd3结构中使用d3和json的多线图

[英]Multi line chart using d3 and json in a nvd3 structure

I'm trying to create a multi line chart using d3 and data in a json format. 我正在尝试使用d3和json格式的数据创建多线图。 For some reason my code isn't working. 出于某种原因,我的代码无效。 I haven't been able to find out where I'm doing wrong. 我无法找出我做错的地方。 Have searched the web and read a lot of examples, to no avail. 搜索过网络并阅读了很多例子,但都无济于事。 I've probably stared me blind on the code. 我可能盯着我看不起代码。

In the example, I'm only trying to draw two lines, but the number of lines are not known. 在这个例子中,我只是想绘制两条线,但是线条的数量是未知的。 So I can't hard code it. 所以我不能硬编码。 Does anyone have any tips on where I'm doing wrong? 有没有人对我做错的地方有任何提示?

Jsfiddle link to the code. Jsfiddle链接到代码。 http://jsfiddle.net/6qrcmsnj/3/ http://jsfiddle.net/6qrcmsnj/3/

Here is also the code. 这也是代码。

var w = 700;
var h = 600;
var pad = 80;

var time_format = d3.time.format("%I:%M:%S");

var gd = example_data(4);


var xScale = d3.time.scale()
    .domain(d3.extent(gd[0].data, function(d) { return d[0]; }))
    .range([pad, w - pad]);

var yScale = d3.scale.linear()
    .domain([0, d3.max(gd[0].data, function(d) { return d[1]; })*2])
    .range([h - pad, pad]);

var canvas = d3.select("body")
    .append("svg")
        .attr("class", "chart")
        .attr("width", w)
        .attr("height", h);

var xaxis = d3.svg.axis()
    .scale(xScale)
    .orient("bottom")
    .tickFormat(time_format);

var yaxis = d3.svg.axis()
    .scale(yScale)
    .orient("left");

var line = d3.svg.line()
    .x(function(d) { return xScale(d[0]); })
    .y(function(d) { return yScale(d[1]); })
    .interpolate("linear");

// Just for a grey background.
canvas.append("rect")
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("fill", "#E8E8E8");

// Add x-axis.
canvas.append("g")
    .attr("class", "axis")
    .attr("transform","translate(0," + (h - pad) + ")")
    .call(xaxis)
    .selectAll("text")
        .style("text-anchor", "end")
        .attr("dx", "-.8em")
        .attr("dy", ".15em")
        .attr("transform", function(d) {
                return "rotate(-65)"
                });

// Add y-axis
canvas.append("g")
    .attr("class", "axis")
    .attr("transform", "translate(" + pad + ", 0)")
    .call(yaxis);

// Add line
canvas.selectAll("path")
    .data(gd)
    .enter().append("path")
    .attr("d", line(gd.data))
    .attr("stroke", "black")
    .attr("stroke-width", 1)
    .attr("fill", "none");

function example_data(val) {

    if (val == "4") {
        return [
            { "label" : "Data_1", "data" : [ [ 1404438592000, 21.09 ], [ 1404438593000, 10.85 ], [ 1404438594000, 15.74 ], [ 1404438595000, 20.86 ], [ 1404438596000, 10.83 ], [ 1404438597000, 8.92 ], [ 1404438598000, 23.68 ], [ 1404438599000, 20.68 ], [ 1404438600000, 14.68 ], [ 1404438601000, 4.65 ]] }, 
            { "label" : "Data_2", "data" : [ [ 1404438592000, 3.219 ], [ 1404438593000, 1.641 ], [ 1404438594000, 6.68 ], [ 1404438595000, 2.543 ], [ 1404438596000, 8.522 ], [ 1404438597000, 4.616 ], [ 1404438598000, 9.703 ], [ 1404438599000, 3.737 ], [ 1404438600000, 8.752 ], [ 1404438601000, 1.791 ]]}
        ];
    }           
}

I copied your jsfiddle to a stack snippet that can be viewed below. 我将你的jsfiddle复制到一个可以在下面查看的堆栈片段。 Looping through the data creating a line for each post. 循环遍历数据,为每个帖子创建一条线。

for(var i = 0; i < gd.length; i++)
{
   canvas.append("path")
   .data([gd[i].data])
   .attr("d", line).attr("class", "line" + i);
}

 var w = 700; var h = 600; var pad = 80; var time_format = d3.time.format("%I:%M:%S"); var gd = example_data(4); var xScale = d3.time.scale() .domain(d3.extent(gd[0].data, function(d) { return d[0]; })) .range([pad, w - pad]); var yScale = d3.scale.linear() .domain([0, d3.max(gd[0].data, function(d) { return d[1]; }) * 2]) .range([h - pad, pad]); var canvas = d3.select("body") .append("svg") .attr("class", "chart") .attr("width", w) .attr("height", h); var xaxis = d3.svg.axis() .scale(xScale) .orient("bottom") .tickFormat(time_format); var yaxis = d3.svg.axis() .scale(yScale) .orient("left"); var line = d3.svg.line() .x(function(d) { return xScale(d[0]); }) .y(function(d) { return yScale(d[1]); }) .interpolate("linear"); // Just for a grey background. canvas.append("rect") .attr("width", "100%") .attr("height", "100%") .attr("fill", "#E8E8E8"); // Add x-axis. canvas.append("g") .attr("class", "axis") .attr("transform", "translate(0," + (h - pad) + ")") .call(xaxis) .selectAll("text") .style("text-anchor", "end") .attr("dx", "-.8em") .attr("dy", ".15em") .attr("transform", function(d) { return "rotate(-65)" }); // Add y-axis canvas.append("g") .attr("class", "axis") .attr("transform", "translate(" + pad + ", 0)") .call(yaxis); for (var i = 0; i < gd.length; i++) { // Add line canvas.append("path") .data([gd[i].data]) .attr("d", line).attr("class", "line" + i); } function example_data(val) { if (val == "4") { return [{ "label": "Data_1", "data": [ [1404438592000, 21.09], [1404438593000, 10.85], [1404438594000, 15.74], [1404438595000, 20.86], [1404438596000, 10.83], [1404438597000, 8.92], [1404438598000, 23.68], [1404438599000, 20.68], [1404438600000, 14.68], [1404438601000, 4.65] ] }, { "label": "Data_2", "data": [ [1404438592000, 3.219], [1404438593000, 1.641], [1404438594000, 6.68], [1404438595000, 2.543], [1404438596000, 8.522], [1404438597000, 4.616], [1404438598000, 9.703], [1404438599000, 3.737], [1404438600000, 8.752], [1404438601000, 1.791] ] }]; } } 
 .axis path, .axis line { fill: none; stroke: black; shape-rendering: crispEdges; } .line0 { fill: none; stroke: steelblue; stroke-width: 1.5px; } .line1 { fill: none; stroke: red; stroke-width: 1.5px; } 
 <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> </head> <body> </body> </html> 

@LarThoren method will certainly work but with d3 we like to avoid explicit looping. @LarThoren方法肯定会起作用但是d3我们希望避免显式循环。 Your version misses two things: 你的版本错过了两件事:

canvas.selectAll(".series") //<-- don't selectAll with "path", there are other paths in the axis and you selection needs to be more specific
  .data(gd)
  .enter()
  .append("path")
  .attr("d", function(d){ //<-- gd is out of scope here, you need to use the accessor function
    return line(d.data);
  }) 
  .attr("class", "series")
  .attr("stroke", "black")
  .attr("stroke-width", 1)
  .attr("fill", "none");

Full working code: 完整的工作代码:

 var w = 700; var h = 600; var pad = 80; var time_format = d3.time.format("%I:%M:%S"); var gd = example_data(4); var xScale = d3.time.scale() .domain(d3.extent(gd[0].data, function(d) { return d[0]; })) .range([pad, w - pad]); var yScale = d3.scale.linear() .domain([0, d3.max(gd[0].data, function(d) { return d[1]; })*2]) .range([h - pad, pad]); var canvas = d3.select("body") .append("svg") .attr("class", "chart") .attr("width", w) .attr("height", h); var xaxis = d3.svg.axis() .scale(xScale) .orient("bottom") .tickFormat(time_format); var yaxis = d3.svg.axis() .scale(yScale) .orient("left"); var line = d3.svg.line() .x(function(d) { return xScale(d[0]); }) .y(function(d) { return yScale(d[1]); }) .interpolate("linear"); // Just for a grey background. canvas.append("rect") .attr("width", "100%") .attr("height", "100%") .attr("fill", "#E8E8E8"); // Add x-axis. canvas.append("g") .attr("class", "axis") .attr("transform","translate(0," + (h - pad) + ")") .call(xaxis) .selectAll("text") .style("text-anchor", "end") .attr("dx", "-.8em") .attr("dy", ".15em") .attr("transform", function(d) { return "rotate(-65)" }); // Add y-axis canvas.append("g") .attr("class", "axis") .attr("transform", "translate(" + pad + ", 0)") .call(yaxis); // Add line canvas.selectAll(".series") .data(gd) .enter() .append("path") .attr("d", function(d){ return line(d.data); }) .attr("class", "series") .attr("stroke", "black") .attr("stroke-width", 1) .attr("fill", "none"); function example_data(val) { if (val == "4") { return [ { "label" : "Data_1", "data" : [ [ 1404438592000, 21.09 ], [ 1404438593000, 10.85 ], [ 1404438594000, 15.74 ], [ 1404438595000, 20.86 ], [ 1404438596000, 10.83 ], [ 1404438597000, 8.92 ], [ 1404438598000, 23.68 ], [ 1404438599000, 20.68 ], [ 1404438600000, 14.68 ], [ 1404438601000, 4.65 ]] }, { "label" : "Data_2", "data" : [ [ 1404438592000, 3.219 ], [ 1404438593000, 1.641 ], [ 1404438594000, 6.68 ], [ 1404438595000, 2.543 ], [ 1404438596000, 8.522 ], [ 1404438597000, 4.616 ], [ 1404438598000, 9.703 ], [ 1404438599000, 3.737 ], [ 1404438600000, 8.752 ], [ 1404438601000, 1.791 ]]} ]; } } 
 .axis path, .axis line { fill: none; stroke: black; shape-rendering: crispEdges; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 

two changes 两个变化

.attr("d", line(gd.data))

should be 应该

.attr("d", function (d) { return line(d.data) })

and path first and then add axis. 和路径首先然后添加轴。 It should work. 它应该工作。 Basically selectAll('path') picking up path element from axis element. 基本上selectAll('path')从轴元素中拾取路径元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM