forked from nikita/muzika-gromche
50 lines
1.8 KiB
TypeScript
50 lines
1.8 KiB
TypeScript
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<Px>;
|
|
}
|
|
|
|
export function useVeiwportWheel(
|
|
target: MaybeRefOrGetter<HTMLElement | null>,
|
|
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,
|
|
});
|
|
}
|