score:1

Accepted answer

For context, this is from some code that implements chart brushing:

function brushed() {
  if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
  var s = d3.event.selection || x2.range();
  x.domain(s.map(x2.invert, x2));
  focus.select(".area").attr("d", area);
  focus.select(".axis--x").call(xAxis);
  svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
      .scale(width / (s[1] - s[0]))
      .translate(-s[0], 0));
}

We already have x and x2 initialised as two time scales:

var x = d3.scaleTime().range([0, width]),
x2 = d3.scaleTime().range([0, width])

and s is initialised as

var s = d3.event.selection || x2.range();

(where the d3.event is a brushing event)

The line

x.domain(s.map(x2.invert, x2));

sets the x scale domain by running x2.invert on each item in array s with x2 as the this value. In practice, this means you are running

x.domain( x2.invert( s[0] ), x2.invert( s[1] ) );

as there are only two values in s and the this context does not affect the invert function. In terms of the visualisation, this is setting the time span covered by the large chart by converting the pixel values of the edges of the selection box in the bottom chart into dates on the large chart.

To briefly summarise the whole function:

function brushed() {
  if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
  // get the edges of the selection box or use the maximum values (in x2.range)
  var s = d3.event.selection || x2.range();
  // convert those pixel values into dates, and set the x scale domain to those values
  x.domain(s.map(x2.invert, x2));
  // redraw the top graph contents to show only the area within the x domain
  focus.select(".area").attr("d", area);
  // redraw the top graph's x axis with the updated x scale domain
  focus.select(".axis--x").call(xAxis);
  // zoom the overlay of the top graph to reflect the new x domain
  // so that any zoom operations will scale correctly
  svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
      .scale(width / (s[1] - s[0]))
      .translate(-s[0], 0));
}

Related Query

More Query from same tag