import type { Px, ZoomRaw } from "@/lib/units"; import { useEventListener } from "@vueuse/core"; import type { MaybeRefOrGetter, Ref } from "vue"; import type { UseZoomAxis } from "../useZoomAxis"; export interface UseVeiwportWheelOptions { axisHorizontal: UseZoomAxis; axisVertical: UseZoomAxis; scrollOffsetLeft: Ref; } export function useVeiwportWheel( target: MaybeRefOrGetter, options: UseVeiwportWheelOptions, ) { function handler(event: WheelEvent) { // Note: Math.random() prevents console output history from collapsing same entries. // console.log("WHEEEEEL", Math.random().toFixed(3), event.deltaX, event.deltaY, event.target, event); // TODO: Ignore Ctrl key because it intercepts touchpad pinch to zoom? // TODO: what if the user doesn't use a touchpad, and thus has // no way to scroll horizontally other than by dragging a scrollbar? const ignoreCtrlWheel = false; // Note: this hardcoded value feels good enough both for discrete mouse wheel and precise touchpad. const ZOOM_RAW_FACTOR = 100; if (event.shiftKey) { event.preventDefault(); event.stopPropagation(); event.stopImmediatePropagation(); options.axisVertical.zoom.raw.value -= event.deltaY / ZOOM_RAW_FACTOR; } else if (event.altKey) { event.preventDefault(); event.stopPropagation(); event.stopImmediatePropagation(); options.axisHorizontal.zoom.raw.value -= event.deltaY / ZOOM_RAW_FACTOR; } else if (event.ctrlKey && !ignoreCtrlWheel) { event.preventDefault(); event.stopPropagation(); event.stopImmediatePropagation(); options.scrollOffsetLeft.value += event.deltaY; } } return useEventListener(target, "wheel", handler, { passive: false, }); }