Skip to content

Commit

Permalink
Allow interacting with canvas through other interactive elements
Browse files Browse the repository at this point in the history
  • Loading branch information
axelboc committed Aug 11, 2023
1 parent 4dce043 commit 137cdec
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 11 deletions.
3 changes: 2 additions & 1 deletion apps/storybook/src/FloatingToolbar.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FloatingControl, VisCanvas } from '@h5web/lib';
import { DefaultInteractions, FloatingControl, VisCanvas } from '@h5web/lib';
import { useToggle } from '@react-hookz/web';
import type { Meta, StoryObj } from '@storybook/react';

Expand All @@ -24,6 +24,7 @@ export const Default = {
ordinateConfig={{ visDomain: [50, 100], showGrid: true }}
title={withTitle ? 'Plot title' : undefined}
>
<DefaultInteractions />
<FloatingControl>
<button
type="button"
Expand Down
26 changes: 16 additions & 10 deletions packages/lib/src/interactions/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,15 @@ export function useZoomOnSelection() {
}

function useWheelCapture() {
const { domElement } = useThree((state) => state.gl);
const canvasWrapper = useCanvasWrapper();

const onWheel = useCallback((evt: WheelEvent) => {
evt.preventDefault();
}, []);

// Handler must be registed as non-passive for `preventDefault` to have an effect
// (React's `onWheel` prop registers handlers as passive)
useEventListener(domElement, 'wheel', onWheel, { passive: false });
useEventListener(canvasWrapper, 'wheel', onWheel, { passive: false });
}

export function useZoomOnWheel(
Expand Down Expand Up @@ -122,7 +122,7 @@ export function useZoomOnWheel(
export function useCanvasEvents(callbacks: CanvasEventCallbacks): void {
const { onPointerDown, onPointerMove, onPointerUp, onWheel } = callbacks;

const { domElement } = useThree((state) => state.gl);
const canvasWrapper = useCanvasWrapper();
const camera = useThree((state) => state.camera);
const { htmlToWorld, worldToData } = useVisCanvasContext();

Expand Down Expand Up @@ -175,10 +175,10 @@ export function useCanvasEvents(callbacks: CanvasEventCallbacks): void {
[processEvent, onWheel],
);

useEventListener(domElement, 'pointerdown', handlePointerDown);
useEventListener(domElement, 'pointermove', handlePointerMove);
useEventListener(domElement, 'pointerup', handlePointerUp);
useEventListener(domElement, 'wheel', handleWheel);
useEventListener(canvasWrapper, 'pointerdown', handlePointerDown);
useEventListener(canvasWrapper, 'pointermove', handlePointerMove);
useEventListener(canvasWrapper, 'pointerup', handlePointerUp);
useEventListener(canvasWrapper, 'wheel', handleWheel);
}

export function useInteraction(id: string, value: InteractionEntry) {
Expand All @@ -197,8 +197,6 @@ export function useInteraction(id: string, value: InteractionEntry) {
}

export function useModifierKeyPressed(modifierKeys: ModifierKey[]): boolean {
const { domElement } = useThree((state) => state.gl);

const [pressedKeys] = useState(new Map<string, boolean>());
const [allPressed, toggleAllPressed] = useToggle(false);

Expand All @@ -224,7 +222,8 @@ export function useModifierKeyPressed(modifierKeys: ModifierKey[]): boolean {
/* Keyboard events are triggered only when the window has focus.
* This ensures that the `allPressed` state gets updated (if needed) when the
* user starts interacting with the canvas while the window is out of focus. */
useEventListener(domElement, 'pointerdown', (event: PointerEvent) => {
const canvasWrapper = useCanvasWrapper();
useEventListener(canvasWrapper, 'pointerdown', (event: PointerEvent) => {
MODIFIER_KEYS.forEach((key) => {
pressedKeys.set(key, event.getModifierState(key));
});
Expand All @@ -234,3 +233,10 @@ export function useModifierKeyPressed(modifierKeys: ModifierKey[]): boolean {

return allPressed;
}

function useCanvasWrapper(): HTMLDivElement {
return useThree(
(state) =>
state.gl.domElement.parentElement?.parentElement as HTMLDivElement,
);
}
1 change: 1 addition & 0 deletions packages/lib/src/vis/shared/VisCanvas.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
grid-area: canvas;
position: relative; /* for `.r3fRoot`, `.svgOverlay`, `.floatingToolbar`, overflowing annotations, etc. */
background-color: var(--h5w-canvas--bgColor, transparent);
user-select: none; /* selection may be restored on specific elements as needed (annotations, etc.) */

/*
* `.canvasWrapper` and `.r3fRoot` are implicitely stacked at `z-index: 0`, so
Expand Down

0 comments on commit 137cdec

Please sign in to comment.