D3js - create and easily update a multi-line chart

I created a small test line chart using D3, but since I'm completely new to the library, I'm not sure if the best way is to add some lines to the chart, at the moment I only have one line displayed in fiddle .

I would like to display 2 lines in the diagram, but I am not sure how to achieve this without copying the code, which I am sure will be very inefficient, since I would like to update / revitalize the graph at regular intervals based on when the user is selected.

Instead of this

var data = [12345,22345,32345,42345,52345,62345,72345,82345,92345,102345,112345,122345,132345,142345]; 

I would like to display something like this,

 var data = [ [12345,42345,3234,22345,72345,62345,32345,92345,52345,22345], // line one [1234,4234,3234,2234,7234,6234,3234,9234,5234,2234] // line two ]; 

Is it possible? If so, what would be the best way to approach this so that I can easily update / animate the chart if necessary?

Note. I'm just trying to learn and get acquainted with the best practices of D3 and the library as a whole. Thanks.

+8
javascript linechart
source share
1 answer

It is possible and reasonable. There is a tutorial, which is D3 An embedded selection guide that describes data nesting.

Below is the code I cracked from your violin to demonstrate this.

 var data = [ [12345,42345,3234,22345,72345,62345,32345,92345,52345,22345], [1234,4234,3234,2234,7234,6234,3234,9234,5234,2234] ]; var width = 625, height = 350; var x = d3.scale.linear() .domain([0,data[0].length]) // Hack. Computing x-domain from 1st array .range([0, width]); var y = d3.scale.linear() .domain([0,d3.max(data[0])]) // Hack. Computing y-domain from 1st array .range([height, 0]); var line = d3.svg.line() .x(function(d,i) { return x(i); }) .y(function(d) { return y(d); }); var area = d3.svg.area() .x(line.x()) .y1(line.y()) .y0(y(0)); var svg = d3.select("body").append("svg") //.datum(data) .attr("width", width) .attr("height", height) //.append("g"); var lines = svg.selectAll( "g" ) .data( data ); // The data here is two arrays // for each array, create a 'g' line container var aLineContainer = lines .enter().append("g"); /*svg.append("path") .attr("class", "area") .attr("d", area);*/ aLineContainer.append("path") .attr("class", "area") .attr("d", area); /*svg.append("path") .attr("class", "line") .attr("d", line);*/ aLineContainer.append("path") .attr("class", "line") .attr("d", line); /*svg.selectAll(".dot") .data(data) .enter().append("circle") .attr("class", "dot") .attr("cx", line.x()) .attr("cy", line.y()) .attr("r", 3.5);*/ // Access the nested data, which are values within the array here aLineContainer.selectAll(".dot") .data( function( d, i ) { return d; } ) // This is the nested data call .enter() .append("circle") .attr("class", "dot") .attr("cx", line.x()) .attr("cy", line.y()) .attr("r", 3.5);​ 

One drawback is that I calculated the domain for the x and y axes from the first array, which is a hack but not relevant for your question.

Sample of output image

+12
source share

All Articles