Hi @AbreezaSaleem! Let’s go through those cells in order of data flow:
1a. chart
:
This cell produces a DOM element (the chart SVG), but also “sneakily” attaches an .update()
method to it:
// ...
return Object.assign(svg.node(), {
update(focusX, focusY) {
gx.call(xAxis, focusX, height);
gy.call(yAxis, focusY, data.y);
path.attr("d", area(focusX, focusY));
}
});
We can call chart.update(fromDate, toDate)
from another cell to have the chart change its visible range. (As an aside, I think that focusX
and focusY
are legacy names from another implementation.)
1b. viewof focus
:
This cell is a view
, a special Observable construct. Think of it as a custom form element with a value
property that reflects its user input. When you brush, this value property is set to the selected range:
// ...
function brushed({selection}) {
if (selection) {
svg.property("value", selection.map(x.invert, x).map(d3.utcDay.round));
svg.dispatch("input");
}
}
Other cells can reference this value directly as focus
(instead of viewof focus
).
2. update
:
This cell ties the previous two together. Whenever we get a new value for focus
, Observable will automatically rerun this cell. The important line here is this one:
// ...
chart.update(x.copy().domain(focus), y.copy().domain([0, maxY]));
Sadly, as per @Fil’s comment, this example does not yet seem to implement zoom.
To make it work for Observable, we’d likely implement chart as a viewof, too, and ensure that its value can be set from outside. We can then bind both viewof focus
and viewof chart
together so that they update each other: Synchronized Inputs / Observable | Observable