[improvement] zoom (#577)

* improve zoom events, skip pinch on desktop

* Update useZoomEvents.ts
pull/581/head
Steve Ruiz 2022-02-15 12:21:31 +00:00 zatwierdzone przez GitHub
rodzic ee71a37b40
commit 3a08473d85
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
3 zmienionych plików z 70 dodań i 15 usunięć

Wyświetl plik

@ -28,23 +28,29 @@ export function useZoomEvents<T extends HTMLElement>(zoom: number, ref: React.Re
}, [])
const handleWheel = React.useCallback<Handler<'wheel', WheelEvent>>(
({ delta: wheelDelta, event: e }) => {
({ event: e }) => {
e.preventDefault()
if (inputs.isPinching) return
const { offset } = normalizeWheel(e)
// alt+scroll or ctrl+scroll = zoom
if ((e.altKey || e.ctrlKey) && e.buttons === 0) {
if ((e.altKey || e.ctrlKey || e.metaKey) && e.buttons === 0) {
const point = inputs.pointer?.point ?? [bounds.width / 2, bounds.height / 2]
const info = inputs.pinch(point, point)
const delta = [...point, wheelDelta[1]]
const delta = [...point, offset[1]]
const info = inputs.pan(delta, e)
callbacks.onZoom?.({ ...info, delta }, e)
return
}
// otherwise pan
const delta = e.shiftKey
? // shift+scroll = pan horizontally
[wheelDelta[1], 0]
: // scroll = pan vertically (or in any direction on a trackpad)
[...wheelDelta]
if (inputs.isPinching) return
const delta = Vec.mul(
e.shiftKey
? // shift+scroll = pan horizontally
[offset[1], 0]
: // scroll = pan vertically (or in any direction on a trackpad)
[...offset],
0.5
)
if (Vec.isEqual(delta, [0, 0])) return
const info = inputs.pan(delta, e)
callbacks.onPan?.(info, e)
@ -56,6 +62,7 @@ export function useZoomEvents<T extends HTMLElement>(zoom: number, ref: React.Re
Handler<'pinch', WheelEvent | PointerEvent | TouchEvent | WebKitGestureEvent>
>(
({ origin, event }) => {
if (event instanceof WheelEvent) return
const elm = ref.current
if (!elm || !(event.target === elm || elm.contains(event.target as Node))) return
const info = inputs.pinch(origin, origin)
@ -71,7 +78,8 @@ export function useZoomEvents<T extends HTMLElement>(zoom: number, ref: React.Re
const handlePinch = React.useCallback<
Handler<'pinch', WheelEvent | PointerEvent | TouchEvent | WebKitGestureEvent>
>(
({ origin, event, offset }) => {
({ origin, offset, event }) => {
if (event instanceof WheelEvent) return
const elm = ref.current
if (!(event.target === elm || elm?.contains(event.target as Node))) return
if (!rOriginPoint.current) return
@ -122,3 +130,47 @@ export function useZoomEvents<T extends HTMLElement>(zoom: number, ref: React.Re
}
)
}
// Reasonable defaults
const PIXEL_STEP = 10
const LINE_HEIGHT = 40
const PAGE_HEIGHT = 800
function normalizeWheel(event: any) {
let sX = 0,
sY = 0, // spinX, spinY
pX = 0,
pY = 0 // pixelX, pixelY
// Legacy
if ('detail' in event) sY = event.detail
if ('wheelDelta' in event) sY = -event.wheelDelta / 120
if ('wheelDeltaY' in event) sY = -event.wheelDeltaY / 120
if ('wheelDeltaX' in event) sX = -event.wheelDeltaX / 120
// side scrolling on FF with DOMMouseScroll
if ('axis' in event && event.axis === event.HORIZONTAL_AXIS) {
sX = sY
sY = 0
}
pX = 'deltaX' in event ? event.deltaX : sX * PIXEL_STEP
pY = 'deltaY' in event ? event.deltaY : sY * PIXEL_STEP
if ((pX || pY) && event.deltaMode) {
if (event.deltaMode == 1) {
// delta in LINE units
pX *= LINE_HEIGHT
pY *= LINE_HEIGHT
} else {
// delta in PAGE units
pX *= PAGE_HEIGHT
pY *= PAGE_HEIGHT
}
}
// Fall-back if spin cannot be determined
if (pX && !sX) sX = pX < 1 ? -1 : 1
if (pY && !sY) sY = pY < 1 ? -1 : 1
return { spin: [sX, sY], offset: [pX, pY] }
}

Wyświetl plik

@ -3059,7 +3059,9 @@ export class TldrawApp extends StateManager<TDSnapshot> {
return this
}
onPinchStart: TLPinchEventHandler = (info, e) => this.currentTool.onPinchStart?.(info, e)
onPinchStart: TLPinchEventHandler = (info, e) => {
this.currentTool.onPinchStart?.(info, e)
}
onPinchEnd: TLPinchEventHandler = (info, e) => this.currentTool.onPinchEnd?.(info, e)
@ -3086,12 +3088,12 @@ export class TldrawApp extends StateManager<TDSnapshot> {
const delta =
e.deltaMode === WheelEvent.DOM_DELTA_PIXEL
? info.delta[2] / 500
? info.delta[2] / 50
: e.deltaMode === WheelEvent.DOM_DELTA_LINE
? info.delta[2] / 100
? info.delta[2] / 50
: info.delta[2] / 2
this.zoomBy(delta, this.centerPoint)
this.zoomBy(delta, info.point)
this.onPointerMove(info, e as unknown as React.PointerEvent)
}

Wyświetl plik

@ -2,6 +2,7 @@ import {
TLKeyboardEventHandler,
TLPinchEventHandler,
TLPointerEventHandler,
TLWheelEventHandler,
Utils,
} from '@tldraw/core'
import type { TldrawApp } from '../internal'