Getting to grips with pointer events

Inspired by @Fil’s Multitouch done right I wanted to take a pop at using pointer events. However, I’ve not quite sussed it.

In this notebook I’ve added a tooltip to the D3 bar chart example. It works fine on my computer, but on my phone it behaves unpredictably. The intended behaviour is that the tooltip content updates as the user scrolls over the bars, but this doesn’t always work, as you can see below.

tooltip
Recorded on iOS 13.6, which appears to be supported.

Any tips on how to get this working would be gratefully received! The relevant code appears at the bottom of the chart cell. Pasted here for reference.

  const tooltip = new Tooltip();
  bars
    .on("touchstart", event => event.preventDefault())
    .on("pointerover", (_, d) => tooltip.show(d))
    .on("pointermove", event => tooltip.position(...d3.pointer(event)))
    .on("pointerleave", () => tooltip.hide())
  svg.append(() => tooltip.node);

More broadly, I’m keen to learn what the best practice is for cross-platform interactivity. From what I can see the majority of interactive D3 examples still use mouse and touch events.

Ah interesting! It seems that on iPhone the bar captures the pointer (ie all subsequent events in the same gesture are bound to the first element which accepted the gesture).

If we explicitly release it it will work as expected… but apparently we must release it in pointermove not pointerenter.

I’m sending you a suggestion which fixes it for me.

(Note that pointerleave is obsolete and should be pointerout.)

Capture d’écran 2020-09-18 à 14.39.39

Fantastic, thanks Fil!

1 Like