Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Programmatically assigning/clearing the pointer (tip) value #2188

Open
mbostock opened this issue Oct 6, 2024 · 1 comment
Open

Programmatically assigning/clearing the pointer (tip) value #2188

mbostock opened this issue Oct 6, 2024 · 1 comment
Labels
enhancement New feature or request

Comments

@mbostock
Copy link
Member

mbostock commented Oct 6, 2024

I have a set of plots (effectively small multiples) but they are generated with separate instances of Plot.plot. These plots have a tip, and I would like to ensure that at most one tip is visible at a time across plots. Since Plot tracks the tip state within each rendered plot separately, if I do nothing then I can click on each plot to make the tip sticky, and end up with many simultaneously visible tips. This is especially noticeable on mobile when it often occurs unintentionally (because tips are effectively sticky by default and are hard to clear).

I can clear the tip programmatically like so:

plot.dispatchEvent(new PointerEvent("pointerdown", {pointerType: "mouse", bubbles: true}));

But, I thought it would be nicer if there were a more discoverable and supported API. Here are a few possibilities I’m considering.

1. Assigning plot.value

plot.value = null;

This would be symmetric to getting the pointed value, which is appealing. But I think it’s too ambiguous for setting it: you’d need to set it to the exact datum, which wouldn’t work in many cases when the data is not unique. Plus you could have multiple marks with pointer interactions — maybe you want to control them independently, or at least maybe they each need different hints to know what should be pointed.

2. A mark.point method

mark.point(value);
mark.pointIndex(index); // or if an index is preferred

If a mark has the pointer interaction applied, a mark.point method is assigned to the mark, allowing the pointed value to be controlled programmatically. Assigning a new value re-renders the mark (via the render transform) and re-assigns plot.value, but does not emit an input event or re-render other marks. In cases where it is awkward to specify the pointed value by data, mark.pointIndex(index) can be used to specify the index of the pointed data. mark.point(value) is a convenience method for mark.pointIndex(data.indexOf(value)).

When using the tip option, it could be mark.tip.point(value) for the same effect.

This approach requires retaining a reference to the mark with the pointer interaction applied (or equivalently the mark with the tip applied), but that should be reasonable. I suppose we could also have plot.point that points at all pointer’d marks, too.

@mbostock mbostock added the enhancement New feature or request label Oct 6, 2024
@mbostock
Copy link
Member Author

mbostock commented Oct 6, 2024

A related idea here would be to have a pointerScope option that controls the scope of the pointer state such that multiple plots could share the same exclusivity. The current pointer state is stored in a WeakMap here:

// Isolate state per-pointer, per-plot; if the pointer is reused by
// multiple marks, they will share the same state (e.g., sticky modality).
let state = states.get(svg);

If we could use a shared key across multiple charts, then we could make the pointers exclusive across charts. Maybe that’s something like:

Plot.dot(data, {tip: {pointerScope: scope}}).plot()

where scope is a Symbol that is shared across plots.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant