Skip to content

Commit fd5e0d5

Browse files
Filmbostock
andauthored
pointer dataflow (#1630)
* closes #1628 * dispatch on render * textarea * “debounce” --------- Co-authored-by: Mike Bostock <[email protected]>
1 parent 82b7433 commit fd5e0d5

File tree

5 files changed

+429
-3
lines changed

5 files changed

+429
-3
lines changed

src/interactions/pointer.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ function pointerK(kx, ky, {x, y, px, py, maxRadius = 40, channels, render, ...op
2222
// response to pointer events.
2323
render: composeRender(function (index, scales, values, dimensions, context, next) {
2424
const svg = context.ownerSVGElement;
25+
const {data} = context.getMarkState(this);
2526

2627
// Isolate state per-pointer, per-plot; if the pointer is reused by
2728
// multiple marks, they will share the same state (e.g., sticky modality).
@@ -118,8 +119,9 @@ function pointerK(kx, ky, {x, y, px, py, maxRadius = 40, channels, render, ...op
118119
}
119120
g.replaceWith(r);
120121
}
121-
state.roots[renderIndex] = r;
122-
return (g = r);
122+
state.roots[renderIndex] = g = r;
123+
context.dispatchValue(i == null ? null : data[i]);
124+
return r;
123125
}
124126

125127
function pointermove(event) {

src/plot.d.ts

+3
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,9 @@ export interface Plot {
370370
* scales.
371371
*/
372372
legend(name: ScaleName, options?: LegendOptions): SVGSVGElement | HTMLElement | undefined;
373+
374+
/** For interactive plots, the current value. */
375+
value?: any;
373376
}
374377

375378
/**

src/plot.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ export function plot(options = {}) {
153153
const context = createContext(options);
154154
const document = context.document;
155155
const svg = creator("svg").call(document.documentElement);
156+
let figure = svg; // replaced with the figure element, if any
156157
context.ownerSVGElement = svg;
157158
context.className = className;
158159
context.projection = createProjection(options, subdimensions);
@@ -169,6 +170,13 @@ export function plot(options = {}) {
169170
return {...state, channels: {...state.channels, ...facetState?.channels}};
170171
};
171172

173+
// Allows e.g. the pointer transform to support viewof.
174+
context.dispatchValue = (value) => {
175+
if (figure.value === value) return;
176+
figure.value = value;
177+
figure.dispatchEvent(new Event("input", {bubbles: true}));
178+
};
179+
172180
// Reinitialize; for deriving channels dependent on other channels.
173181
const newByScale = new Set();
174182
for (const [mark, state] of stateByMark) {
@@ -311,7 +319,6 @@ export function plot(options = {}) {
311319
}
312320

313321
// Wrap the plot in a figure with a caption, if desired.
314-
let figure = svg;
315322
const legends = createLegends(scaleDescriptors, context, options);
316323
if (caption != null || legends.length > 0) {
317324
figure = document.createElement("figure");

0 commit comments

Comments
 (0)