plot icon indicating copy to clipboard operation
plot copied to clipboard

Hover interaction.

Open mbostock opened this issue 4 years ago • 12 comments

It’d be nice to have a tooltip that shows the value nearest the mouse.

mbostock avatar Oct 29 '20 22:10 mbostock

A Voronoi mark could allow this, but more generally I'm wondering if we should have an event-based system for hover.

viewof plot will be dedicated to the selection (or full dataset in absence of a selection). To deal with hover, we should probably create a mechanism such as Plot.plot(………).on("pointermove", …), at the plot (or at the mark) level?

And provide a helper function that knows how to create a tooltip (probably with a title in bold and a multiline text, both optionals).

Fil avatar Dec 17 '20 09:12 Fil

I was thinking that this would be implemented as an invisible mark (say a rect with fill: none and pointer-events: all) which listens for pointer events and then assigns the ownerSVGElement.value and emits an input event (for viewof compatibility). I was further imagining that the value based on the pointer position would be dependent on which (invisible) mark type you chose. For example, you could imagine a mark type suitable for scatterplots that computes x and y positions for the data, and sets the value to the closest point to the mouse; you could also imagine a mark type suitable for line charts that only considers the x position; you could also imagine {brush, brushX, brushY} marks that allow selection instead of searching.

mbostock avatar Dec 17 '20 16:12 mbostock

My remark was more about separating the two signals: if the viewof channel is dedicated to filtering (typically brushing), I don't think it should be used to send information about what the user is hovering, and vice versa?

In the case of a chart which has both brush and hover interactions, you'd want the brush to return "a collection" and update "aggregate charts" downstream. Hovering on clicking on 1 datum would update an "individual view", with lots of details about that datum (that view could be a tooltip mark in the same plot). Typically I think we wouldn't want to mix these two streams, because they have very different purposes and rendering methods. Hence the proposal of dedicating viewof to selection (of a subset of the data), and a different dispatch mechanism for hovering/pointing at one datum.

I can't find a good example right now, the closest thing would be https://observablehq.com/@john-guerra/umap-playground if its brush returned a selection via viewof. (It's a nice dataset btw).

Fil avatar Dec 17 '20 21:12 Fil

Ah. I was thinking you’d only have one or the other (hovering or brushing), but never both.

mbostock avatar Dec 17 '20 22:12 mbostock

I have this data editor plugin example where I'm sending a customEvent with modified data — but getting the actual target of that event is a bit of a mess, and could be helped if we exposed a method of some sort that would trigger when the plot is appended (or ready to append) to the DOM.

Currently this needs an async call and a somewhat chancy heuristic:

    // set chart to the svg and send the initial value
    requestAnimationFrame(() => {
      chart = g.ownerSVGElement;
      if (chart?.parentElement?.nodeName === "FIGURE") chart = chart.parentElement;
      chart.value = data;
      chart.dispatchEvent(new CustomEvent("input", {bubbles: true}));
    });

I'd like to replace it with a method that would have a signature such as ready(index, g, parent, svg parent, data dispatcher)

we need

  • g and (or?) index to know in which facet we are and possibly create event listeners;
  • the parent is the svg or html parent depending on the presence of a figcaption; useful to wrap into something else
  • the svg parent is always the svg; can help to know if we're in svg or html mode, or add styles or target event listeners
  • the data dispatcher is a data flow function to call with data to set the value for viewof

PS: This would be triggered once for each facet, which is not necessarily OK. We might want two such methods: one for each facet, and one for the whole mark.

Fil avatar Apr 21 '21 10:04 Fil

Also need to mention https://observablehq.com/@fil/experimental-plot-tooltip-01 which partly addresses this issue.

Again it shows some problems with (the way I intercept) the creation of a faceted g to add interactive behaviors. A clean method to do this would be welcome.

Fil avatar Apr 21 '21 10:04 Fil

Hi! Is there any way to do interaction with Plot? I tried viewing the above links but most of them are dead. Even if it's a hacky solution, I'd like to know if there is some way to do interaction.

kierangilliam avatar Jun 04 '21 20:06 kierangilliam

I have fixed the links; if you play with them, I would be happy to have feedback.

Fil avatar Jun 06 '21 12:06 Fil

Thanks @Fil for adding super useful interactivity. I am using Plot via npm. Will the tooltip functionality be available from within the package anytime soon?

rdbcasillas avatar Jun 21 '21 08:06 rdbcasillas

I can't give a specific date but interaction is definitely on the roadmap.

Fil avatar Jun 21 '21 08:06 Fil

I've been doing some (comparatively basic) voronoi/tooltip functionality in React Charts and would love to offer any help here that I can, if any. I can say from experience in both building and using several different interaction models for my charts that element-based interaction models are usually easier to build and use compared to arbitrary closest-to-point/trie-like ones. In fact, the same great features that make encoding data to cells, bands, shapes, etc such a breeze in plot would make building this "invisible" interaction layer so much easier than what I've been going through lately 😂 .

Put me to work!

tannerlinsley avatar Jun 25 '21 03:06 tannerlinsley

Reference metricsgraphics

reubano avatar Mar 25 '22 19:03 reubano

Some great reference examples for different chart types by @tannerlinsley: https://codesandbox.io/s/github/tannerlinsley/react-charts/tree/beta/examples/simple?from-embed

tophtucker avatar Mar 29 '23 21:03 tophtucker