Skip to content

Commit bb51b4e

Browse files
authored
composable render transforms (#1576)
1 parent 6b6c813 commit bb51b4e

File tree

4 files changed

+16
-13
lines changed

4 files changed

+16
-13
lines changed

src/interactions/pointer.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ function pointerK(kx, ky, {x, y, px, py, maxRadius = 40, channels, ...options} =
1616
y,
1717
channels,
1818
...options,
19-
render(index, scales, values, dimensions, context) {
20-
const mark = this;
19+
render(index, scales, values, dimensions, context, next) {
2120
const svg = context.ownerSVGElement;
2221

2322
// Isolate state per-pointer, per-plot; if the pointer is reused by
@@ -50,8 +49,8 @@ function pointerK(kx, ky, {x, y, px, py, maxRadius = 40, channels, ...options} =
5049
if (faceted) {
5150
let facetStates = state.facetStates;
5251
if (!facetStates) state.facetStates = facetStates = new Map();
53-
facetState = facetStates.get(mark);
54-
if (!facetState) facetStates.set(mark, (facetState = new Map()));
52+
facetState = facetStates.get(this);
53+
if (!facetState) facetStates.set(this, (facetState = new Map()));
5554
}
5655

5756
// The order of precedence for the pointer position is: px & py; the
@@ -97,7 +96,7 @@ function pointerK(kx, ky, {x, y, px, py, maxRadius = 40, channels, ...options} =
9796
i = ii;
9897
const I = i == null ? [] : [i];
9998
if (faceted) (I.fx = index.fx), (I.fy = index.fy), (I.fi = index.fi);
100-
const r = mark.render(I, scales, values, dimensions, context);
99+
const r = next(I, scales, values, dimensions, context);
101100
if (g) {
102101
// When faceting, preserve swapped mark and facet transforms; also
103102
// remove ARIA attributes since these are promoted to the parent. This

src/mark.d.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ export type RenderFunction = (
4747
/** The plot’s dimensions. */
4848
dimensions: Dimensions,
4949
/** The plot’s context. */
50-
context: Context
50+
context: Context,
51+
/** The next render function; for render transforms only. */
52+
next?: RenderFunction
5153
) => SVGElement | null;
5254

5355
/**

src/mark.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export class Mark {
8484
}
8585
if (render != null) {
8686
if (typeof render !== "function") throw new TypeError(`invalid render transform: ${render}`);
87-
this.renderTransform = render;
87+
this.render = composeRender(render, this.render);
8888
}
8989
}
9090
initialize(facets, facetChannels, plotOptions) {
@@ -136,6 +136,12 @@ export function marks(...marks) {
136136
return marks;
137137
}
138138

139+
function composeRender(r1, r2) {
140+
return function () {
141+
return r1.call(this, ...arguments, r2.bind(this));
142+
};
143+
}
144+
139145
function maybeChannels(channels) {
140146
return Object.fromEntries(
141147
Object.entries(maybeNamed(channels)).map(([name, channel]) => {

src/plot.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ export function plot(options = {}) {
274274
index = mark.filter(index, channels, values);
275275
if (index.length === 0) continue;
276276
}
277-
const node = render(mark, index, scales, values, superdimensions, context);
277+
const node = mark.render(index, scales, values, superdimensions, context);
278278
if (node == null) continue;
279279
svg.appendChild(node);
280280
}
@@ -292,7 +292,7 @@ export function plot(options = {}) {
292292
if (index.length === 0) continue;
293293
if (faceted) (index.fx = f.x), (index.fy = f.y), (index.fi = f.i);
294294
}
295-
const node = render(mark, index, scales, values, subdimensions, context);
295+
const node = mark.render(index, scales, values, subdimensions, context);
296296
if (node == null) continue;
297297
// Lazily construct the shared group (to drop empty marks).
298298
(g ??= select(svg).append("g")).append(() => node).datum(f);
@@ -372,10 +372,6 @@ class Render extends Mark {
372372
render() {}
373373
}
374374

375-
function render(mark, ...args) {
376-
return (mark.renderTransform ?? mark.render).apply(mark, args);
377-
}
378-
379375
// Note: mutates channel.value to apply the scale transform, if any.
380376
function applyScaleTransforms(channels, options) {
381377
for (const name in channels) applyScaleTransform(channels[name], options);

0 commit comments

Comments
 (0)