Skip to content

Commit

Permalink
refactor: use web events everywhere
Browse files Browse the repository at this point in the history
  • Loading branch information
CodyJasonBennett committed Aug 10, 2024
1 parent 1f08b11 commit 55f2989
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 150 deletions.
60 changes: 60 additions & 0 deletions packages/fiber/src/core/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -531,3 +531,63 @@ export function createEvents(store: UseBoundStore<RootState>) {

return { handlePointer }
}

const DOM_EVENTS = {
onClick: ['click', false],
onContextMenu: ['contextmenu', false],
onDoubleClick: ['dblclick', false],
onWheel: ['wheel', true],
onPointerDown: ['pointerdown', true],
onPointerUp: ['pointerup', true],
onPointerLeave: ['pointerleave', true],
onPointerMove: ['pointermove', true],
onPointerCancel: ['pointercancel', true],
onLostPointerCapture: ['lostpointercapture', true],
} as const

/** Default R3F event manager for web */
export function createPointerEvents(store: UseBoundStore<RootState>): EventManager<HTMLElement> {
const { handlePointer } = createEvents(store)

return {
priority: 1,
enabled: true,
compute(event: DomEvent, state: RootState, previous?: RootState) {
// https://github.com/pmndrs/react-three-fiber/pull/782
// Events trigger outside of canvas when moved, use offsetX/Y by default and allow overrides
state.pointer.set((event.offsetX / state.size.width) * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1)
state.raycaster.setFromCamera(state.pointer, state.camera)
},

connected: undefined,
handlers: Object.keys(DOM_EVENTS).reduce(
(acc, key) => ({ ...acc, [key]: handlePointer(key) }),
{},
) as unknown as Events,
update: () => {
const { events, internal } = store.getState()
if (internal.lastEvent?.current && events.handlers) events.handlers.onPointerMove(internal.lastEvent.current)
},
connect: (target: HTMLElement) => {
const { set, events } = store.getState()
events.disconnect?.()
set((state) => ({ events: { ...state.events, connected: target } }))
Object.entries(events.handlers ?? []).forEach(([name, event]) => {
const [eventName, passive] = DOM_EVENTS[name as keyof typeof DOM_EVENTS]
target.addEventListener(eventName, event, { passive })
})
},
disconnect: () => {
const { set, events } = store.getState()
if (events.connected) {
Object.entries(events.handlers ?? []).forEach(([name, event]) => {
if (events && events.connected instanceof HTMLElement) {
const [eventName] = DOM_EVENTS[name as keyof typeof DOM_EVENTS]
events.connected.removeEventListener(eventName, event)
}
})
set((state) => ({ events: { ...state.events, connected: undefined } }))
}
},
}
}
3 changes: 1 addition & 2 deletions packages/fiber/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ export type {
RootState,
} from './core/store'
export type { ThreeEvent, Events, EventManager, ComputeFunction } from './core/events'
export { createEvents } from './core/events'
export { createEvents, createPointerEvents as events } from './core/events'
export type { ObjectMap, Camera } from './core/utils'
export * from './web/Canvas'
export { createPointerEvents as events } from './web/events'
export type { GlobalRenderCallback, GlobalEffectType } from './core/loop'
export * from './core'
3 changes: 1 addition & 2 deletions packages/fiber/src/native.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ export type {
RootState,
} from './core/store'
export type { ThreeEvent, Events, EventManager, ComputeFunction } from './core/events'
export { createEvents } from './core/events'
export { createEvents, createPointerEvents as events } from './core/events'
export type { ObjectMap, Camera } from './core/utils'
export * from './native/Canvas'
export { createTouchEvents as events } from './native/events'
export type { GlobalRenderCallback, GlobalEffectType } from './core/loop'
export * from './core'

Expand Down
20 changes: 10 additions & 10 deletions packages/fiber/src/native/Canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { ExpoWebGLRenderingContext, GLView } from 'expo-gl'
import { useContextBridge, FiberProvider } from 'its-fine'
import { SetBlock, Block, ErrorBoundary, useMutableCallback } from '../core/utils'
import { extend, createRoot, unmountComponentAtNode, RenderProps, ReconcilerRoot } from '../core'
import { createTouchEvents } from './events'
import { createPointerEvents } from '../core/events'
import { RootState, Size } from '../core/store'

export interface CanvasProps extends Omit<RenderProps<HTMLCanvasElement>, 'size' | 'dpr'>, ViewProps {
Expand All @@ -35,7 +35,7 @@ const CanvasImpl = /*#__PURE__*/ React.forwardRef<View, Props>(
children,
style,
gl,
events = createTouchEvents,
events = createPointerEvents,
shadows,
linear,
flat,
Expand Down Expand Up @@ -147,16 +147,16 @@ const CanvasImpl = /*#__PURE__*/ React.forwardRef<View, Props>(
onMoveShouldSetPanResponder: () => true,
onMoveShouldSetPanResponderCapture: () => true,
onPanResponderTerminationRequest: () => true,
onStartShouldSetPanResponderCapture: (e) => handleTouch(e, 'onPointerCapture'),
onPanResponderStart: (e) => handleTouch(e, 'onPointerDown'),
onPanResponderMove: (e) => handleTouch(e, 'onPointerMove'),
onStartShouldSetPanResponderCapture: (e) => handleTouch(e, 'pointercapture'),
onPanResponderStart: (e) => handleTouch(e, 'pointerdown'),
onPanResponderMove: (e) => handleTouch(e, 'pointermove'),
onPanResponderEnd: (e, state) => {
handleTouch(e, 'onPointerUp')
if (Math.hypot(state.dx, state.dy) < 20) handleTouch(e, 'onClick')
handleTouch(e, 'pointerup')
if (Math.hypot(state.dx, state.dy) < 20) handleTouch(e, 'click')
},
onPanResponderRelease: (e) => handleTouch(e, 'onPointerLeave'),
onPanResponderTerminate: (e) => handleTouch(e, 'onLostPointerCapture'),
onPanResponderReject: (e) => handleTouch(e, 'onLostPointerCapture'),
onPanResponderRelease: (e) => handleTouch(e, 'pointerleave'),
onPanResponderTerminate: (e) => handleTouch(e, 'lostpointercapture'),
onPanResponderReject: (e) => handleTouch(e, 'lostpointercapture'),
})
setBind(responder.panHandlers)
}, [])
Expand Down
71 changes: 0 additions & 71 deletions packages/fiber/src/native/events.ts

This file was deleted.

3 changes: 1 addition & 2 deletions packages/fiber/src/web/Canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import type { Options as ResizeOptions } from 'react-use-measure'
import { useContextBridge, FiberProvider } from 'its-fine'
import { isRef, SetBlock, Block, ErrorBoundary, useMutableCallback, useIsomorphicLayoutEffect } from '../core/utils'
import { ReconcilerRoot, extend, createRoot, unmountComponentAtNode, RenderProps } from '../core'
import { createPointerEvents } from './events'
import { DomEvent } from '../core/events'
import { createPointerEvents, DomEvent } from '../core/events'

export interface CanvasProps
extends Omit<RenderProps<HTMLCanvasElement>, 'size'>,
Expand Down
63 changes: 0 additions & 63 deletions packages/fiber/src/web/events.ts

This file was deleted.

0 comments on commit 55f2989

Please sign in to comment.