Search code examples
javascriptd3.jschartsbrush

In d3.js, update main chart to reflect brush state when adding/removing lines


Following this example of using a brush on a d3.js chart, I'm trying to do similar with a line chart where new lines can be added or removed.

I've made a jsFiddle which shows the issue I'm having. Do these two steps:

  1. Use the brush to select a small area of the right-end of the lower chart.
  2. Click the 'add second line' link.

The two issues are:

  1. The upper "focus" chart redraws to its full extent, rather than remaining constrained to the brush's selection.
  2. The second line has a different range of data, and I'd like the brush to remain selecting its existing date range - at the moment it doesn't physically move so looks like its date range has changed.

I'm guessing, for issue 1, I'd need to alter something in the brushed() function?

function brushed() {
  x.domain(brush.empty() ? x2.domain() : brush.extent());
  focus.selectAll("path.line").attr("d", focusLine);
  focus.select(".x.axis").call(xAxis);
}

Or, maybe in renderBrush()? Or in renderLines()? I'm stumped.


Solution

  • First, you don't need to update bottom chart scales, i.e. x2 and y2. Also, since you know dates domain initially after reading the csv, you don't need to update it. So, right after you get the data, you should do the following:

    // Get min and max of all dates for all the lines.
    x.domain([
      d3.min(csvdata, function(d) {
        return d.date;
    
      }),
      d3.max(csvdata, function(d) {
        return d.date;
      })
    ]);
    
    // Get 0 and max of all prices for all the lines.
    y.domain([
      0,
      d3.max(csvdata, function(d) {
        return d.price;     
      })
    ]);
    
    x2.domain(x.domain());
    y2.domain(y.domain());
    

    Complete example is here.