airbnb / visx

🐯 visx | visualization components
https://airbnb.io/visx
MIT License
19.55k stars 719 forks source link

Zoom: Enable customisation of event handlers #1798

Open jsjohann opened 9 months ago

jsjohann commented 9 months ago

We're using @visx/zoom for a project to zoom/pan a combined visualisation of charts. Basically, it's a list of bar charts which can be scrolled. Additionally, the view can be zoomed/panned.

So, to overcome the shared interaction of the scroll wheel to scroll or zoom the view, we would like to use the control-key as key modifier to enable the zooming/panning. As the control-key is used by @use-gesture to trigger the pinch-event, we need to modify the settings used by @visx/zoom to initialise useGesture:

useGesture(
    {
      onDragStart: ({ event }) => {
        if (!(event instanceof KeyboardEvent)) dragStart(event);
      },
      onDrag: ({ event, pinching, cancel }) => {
        if (pinching) {
          cancel();
          dragEnd();
        } else if (!(event instanceof KeyboardEvent)) {
          dragMove(event);
        }
      },
      onDragEnd: dragEnd,
      onPinch: handlePinch,
      onWheel: ({ event, active, pinching }) => {
        if (
          // Outside of Safari, the wheel event is fired together with the pinch event
          pinching ||
          // currently onWheelEnd emits one final wheel event which causes 2x scale
          // updates for the last tick. ensuring that the gesture is active avoids this
          !active
        ) {
          return;
        }
        handleWheel(event);
      },
    },
    { target: containerRef, eventOptions: { passive: false }, drag: { filterTaps: true } },
  );

So, I would like to suggest to enable the customisation of the useGesture-options as well as the event handlers (e.g. handleWheel) through adding additional properties to the Zoom-component, so that we can provide custom handlers/options.

Basically doing something like:

<Zoom<SVGSVGElement>
  height={height}
  width={width}
  onWheel={customHandleWheel}
  useGestureConfig={customUseGestureConfig}
>
  {(zoom) => {
 ...
}}
</Zoom>
williaster commented 9 months ago

Hey @jsjohann , this sounds good to me! Would you be up for a PR to add this config hook? I'd be happy to review and release!

jsjohann commented 9 months ago

@williaster Thanks for the quick answer! Sure, I can try and have a look :)

RamonEspinosa commented 6 months ago

I'll try solving this as it will also solve #1845. I'll follow the approach above and accept a useGestureConfig prop

RamonEspinosa commented 6 months ago

So I ended up accepting a createGestureHandlers prop because I figured out people using this would most likely need access to the ProvidedZoom<ElementType> object in order to use some of its properties