Orjanp
Orjanp

Reputation: 10941

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

Upvotes: 1

Views: 541

Answers (3)

Ravi Hamsa
Ravi Hamsa

Reputation: 4721

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.

Upvotes: 1

Mark
Mark

Reputation: 108567

@LarThoren method will certainly work but with d3 we like to avoid explicit looping. 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>

Upvotes: 1

Lars Thor&#233;n
Lars Thor&#233;n

Reputation: 553

I copied your jsfiddle to a stack snippet that can be viewed below. 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>

Upvotes: 1

Related Questions