Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

d3 Line Chart with enter-update-exit logic

Tags:

d3.js

today I created a simple Bar Chart with the enter-update-exit logic - everything works fine. Now I will do the same with a line chart - the whole dataset for the chart can change at any time, so I will update the chart smoothly. I can't find a good example with a line chart and the enter-update-exit logic (or I'm looking wrong). Currently I have to remember that if the chart is called for the first time or the data to be updated (data has changed) - This is my dirty version:

   var channelGroup = d3.select(".ch1");

// init. Line Chart 
    if (firstLoad) {
    channelGroup
        .append('path')
        .attr("class", "line")
        .style("stroke", channel.Color)
        .transition()
        .ease("linear")
        .duration(animChart / 2)
        .attr('d', line(channel.DataRows));
}
// update Line Chart    
else {
    channelGroup
        .selectAll("path")
        .data([channel.DataRows])
        .transition()
        .ease("linear")
        .duration(animChart / 2)
        .attr("d", function (d) { return line(d); });
}  

how can I realize this in a good manner?... thx!

like image 416
Kollisionskurs Avatar asked Mar 19 '14 13:03

Kollisionskurs


1 Answers

You're mixing up two different approaches, one binding data to the line and the other just passing the data to the line function. Either one could work (so long as you only have the one line), but if you want to get rid of your if/else construct you're still going to need to separate the statements handling entering/appending the element from the statements updating it.

Option 1 (don't bind data, just call the function):

var linegraph = channelGroup.select('path');

if ( linegraph.empty() ) {
     //handle the entering data
     linegraph = channelGroup.append('path')
                      .attr("class", "line")
                      .style("stroke", channel.Color);
}

linegraph
        .transition()
        .ease("linear")
        .duration(animChart / 2)
        .attr('d', line(channel.DataRows));

Option 2 (use a data join):

var linegraph = channelGroup.selectAll("path")
        .data([channel.DataRows]);

linegraph.enter().append('path')
                 .attr("class", "line");

linegraph
        .transition()
        .ease("linear")
        .duration(animChart / 2)
        .attr("d", line); //This is slightly more efficient than
                          //function (d) { return line(d); }
                          //and does the exact same thing.
                          //d3 sees that `line` is a function, and 
                          //therefore calls it with the data as the 
                          //first parameter.
like image 64
AmeliaBR Avatar answered Oct 27 '22 21:10

AmeliaBR