【问题标题】:Multi line chart using d3 and json in a nvd3 structure在 nvd3 结构中使用 d3 和 json 的多折线图
【发布时间】:2016-01-01 04:59:30
【问题描述】:

我正在尝试使用 d3 和 json 格式的数据创建多折线图。出于某种原因,我的代码无法正常工作。我一直无法找出我做错了什么。在网上搜索并阅读了很多示例,但无济于事。我可能对代码视而不见。

在示例中,我只尝试绘制两条线,但不知道线的数量。所以我不能硬编码。有人对我做错的地方有任何提示吗?

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

这里也是代码。

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 ]]}
        ];
    }           
}

【问题讨论】:

    标签: javascript jquery canvas d3.js svg


    【解决方案1】:

    我将您的 jsfiddle 复制到了可以在下面查看的堆栈 sn-p 中。循环遍历数据,为每个帖子创建一行。

    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>

    【讨论】:

    • 感谢您的建议。然而 canvas.selectAll("path") .data(gd) .enter().append("path") .attr("d", function(d) { return line(gd.data); } );做同样的事情。循环遍历数据,为每个数据创建一条线。
    【解决方案2】:

    @LarThoren 方法当然可以,但使用d3 我们希望避免显式循环。您的版本遗漏了两件事:

    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");
    

    完整的工作代码:

    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;
    }
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"&gt;&lt;/script&gt;

    【讨论】:

    • 非常感谢。缺少的“功能”部分只是一个错字。原始代码中有完整的行。不知道为什么我的jsfiddle没有。 “selectAll”部分成功了。现在终于工作了。经过数小时的搜索和阅读,解决方案就这么简单。但我可能不会自己发现。非常感谢。
    【解决方案3】:

    两个变化

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

    应该是

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

    先和路径,然后添加轴。它应该工作。基本上 selectAll('path') 从轴元素中拾取路径元素。

    【讨论】:

    • 这实际上只是一个错字,最终出现在我的 jsfiddle 示例中。原始代码具有整个功能行。感谢您让我意识到这一点。
    猜你喜欢
    • 1970-01-01
    • 2012-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-18
    • 1970-01-01
    • 1970-01-01
    • 2015-12-05
    相关资源
    最近更新 更多