Luke Ehresman
Luke Ehresman

Reputation: 5257

How can I add more time-series data after drawing a D3 line chart?

I have a D3 line chart that loads and displays a lot of live streaming data. In order to make the UI feel faster, I am progressively rendering the chart as data comes in in chunks. So, for example, I may be showing a chart that spans 15 minutes, but load the latest 5 minutes, then load the data from 10 minutes ago, then 15 minutes ago. In that time, I'll re-render the chart 3 times.

My problem is that when I re-render the chart, a line is drawn across the entire chart.

This is best explained through an example:

var end_ts = new Date().getTime();
var range = 60000;
var start_ts = end_ts - range;

var n = 30,
    random = d3.random.normal(0, .2),
    data = d3.range(n).map(function(i) {
      return { time:new Date(end_ts - (n*1000) + i*1000), value:random() };
    });

var margin = {top: 20, right: 20, bottom: 20, left: 40},
    width = 500 - margin.left - margin.right,
    height = 300 - margin.top - margin.bottom;

var x = d3.time.scale()
    .domain([new Date(start_ts), new Date(end_ts)])
    .range([0, width]);

var y = d3.scale.linear()
    .domain([-1, 1])
    .range([height, 0]);

var line = d3.svg.line()
    .x(function(d, i) { return x(d.time); })
    .y(function(d, i) { return y(d.value); });

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

svg.append("defs").append("clipPath")
    .attr("id", "clip")
  .append("rect")
    .attr("width", width)
    .attr("height", height);

var xAxis = d3.svg.axis().scale(x).orient("bottom")
var xAxisGroup = svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + y(0) + ")")
    .call(xAxis);

svg.append("g")
    .attr("class", "y axis")
    .call(d3.svg.axis().scale(y).orient("left"));

var path = svg.append("g")
    .attr("clip-path", "url(#clip)")
  .append("path")
    .datum(data)
    .attr("class", "line")
    .attr("d", line);

// Render the first time
path.attr("d", line)

// Add some more data
for (var i=0; i < 10; i++)
  data.push({time: new Date(start_ts+5000+i*1000), value: random()});

// Render the second time
path.attr("d", line)

See this on jsfiddle: http://jsfiddle.net/DANuz/

Anyone know how to add data to a chart and make this work? Note that it is important that I am adding the newest data first, then older data later. That's the behavior that I need.

Thanks.

Upvotes: 0

Views: 1060

Answers (1)

Scott Cameron
Scott Cameron

Reputation: 5323

The new data you're pushing on to the end of the array is from an earlier time than the data that was there originally. Here are 10 values you push on along with the last 2 that were there previously:

Thu Sep 12 2013 13:18:03 GMT-0700 (Pacific Daylight Time)
Thu Sep 12 2013 13:18:04 GMT-0700 (Pacific Daylight Time)
Thu Sep 12 2013 13:17:10 GMT-0700 (Pacific Daylight Time)
Thu Sep 12 2013 13:17:11 GMT-0700 (Pacific Daylight Time)
Thu Sep 12 2013 13:17:12 GMT-0700 (Pacific Daylight Time)
Thu Sep 12 2013 13:17:13 GMT-0700 (Pacific Daylight Time)
Thu Sep 12 2013 13:17:14 GMT-0700 (Pacific Daylight Time)
Thu Sep 12 2013 13:17:15 GMT-0700 (Pacific Daylight Time)
Thu Sep 12 2013 13:17:16 GMT-0700 (Pacific Daylight Time)
Thu Sep 12 2013 13:17:17 GMT-0700 (Pacific Daylight Time)
Thu Sep 12 2013 13:17:18 GMT-0700 (Pacific Daylight Time)
Thu Sep 12 2013 13:17:19 GMT-0700 (Pacific Daylight Time)

So the is drawing left to right up to 13:18:04 and then it jumps back to 13:17:10 like the data tells it to. You need to make sure the data is sorted by time.

Upvotes: 2

Related Questions