| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392 |
- import type React from 'react'
- import type { TLKeyboardInfo, TLPointerInfo } from './types'
- import { Utils } from './utils'
- import { Vec } from '@tldraw/vec'
- import type { TLBounds } from '+index'
-
- const DOUBLE_CLICK_DURATION = 250
-
- export class Inputs {
- pointer?: TLPointerInfo<string>
-
- keyboard?: TLKeyboardInfo
-
- keys: Record<string, boolean> = {}
-
- isPinching = false
-
- bounds: TLBounds = {
- minX: 0,
- maxX: 640,
- minY: 0,
- maxY: 480,
- width: 640,
- height: 480,
- }
-
- zoom = 1
-
- pointerUpTime = 0
-
- activePointer?: number
-
- pointerIsValid(e: TouchEvent | React.TouchEvent | PointerEvent | React.PointerEvent) {
- if ('pointerId' in e) {
- if (this.activePointer && this.activePointer !== e.pointerId) return false
- }
-
- if ('touches' in e) {
- const touch = e.changedTouches[0]
- if (this.activePointer && this.activePointer !== touch.identifier) return false
- }
-
- return true
- }
-
- touchStart<T extends string>(e: TouchEvent | React.TouchEvent, target: T): TLPointerInfo<T> {
- const { shiftKey, ctrlKey, metaKey, altKey } = e
-
- const touch = e.changedTouches[0]
-
- this.activePointer = touch.identifier
-
- const info: TLPointerInfo<T> = {
- target,
- pointerId: touch.identifier,
- origin: Inputs.getPoint(touch, this.bounds),
- delta: [0, 0],
- point: Inputs.getPoint(touch, this.bounds),
- pressure: Inputs.getPressure(touch),
- shiftKey,
- ctrlKey,
- metaKey: Utils.isDarwin() ? metaKey : ctrlKey,
- altKey,
- spaceKey: this.keys[' '],
- }
-
- this.pointer = info
-
- return info
- }
-
- touchEnd<T extends string>(e: TouchEvent | React.TouchEvent, target: T): TLPointerInfo<T> {
- const { shiftKey, ctrlKey, metaKey, altKey } = e
-
- const touch = e.changedTouches[0]
-
- const info: TLPointerInfo<T> = {
- target,
- pointerId: touch.identifier,
- origin: Inputs.getPoint(touch, this.bounds),
- delta: [0, 0],
- point: Inputs.getPoint(touch, this.bounds),
- pressure: Inputs.getPressure(touch),
- shiftKey,
- ctrlKey,
- metaKey: Utils.isDarwin() ? metaKey : ctrlKey,
- altKey,
- spaceKey: this.keys[' '],
- }
-
- this.pointer = info
-
- this.activePointer = undefined
-
- return info
- }
-
- touchMove<T extends string>(e: TouchEvent | React.TouchEvent, target: T): TLPointerInfo<T> {
- const { shiftKey, ctrlKey, metaKey, altKey } = e
-
- const touch = e.changedTouches[0]
-
- const prev = this.pointer
-
- const point = Inputs.getPoint(touch, this.bounds)
-
- const delta = prev?.point ? Vec.sub(point, prev.point) : [0, 0]
-
- const info: TLPointerInfo<T> = {
- origin: point,
- ...prev,
- target,
- pointerId: touch.identifier,
- point,
- delta,
- pressure: Inputs.getPressure(touch),
- shiftKey,
- ctrlKey,
- metaKey: Utils.isDarwin() ? metaKey : ctrlKey,
- altKey,
- spaceKey: this.keys[' '],
- }
-
- this.pointer = info
-
- return info
- }
-
- pointerDown<T extends string>(e: PointerEvent | React.PointerEvent, target: T): TLPointerInfo<T> {
- const { shiftKey, ctrlKey, metaKey, altKey } = e
-
- const point = Inputs.getPoint(e, this.bounds)
-
- this.activePointer = e.pointerId
-
- const info: TLPointerInfo<T> = {
- target,
- pointerId: e.pointerId,
- origin: point,
- point: point,
- delta: [0, 0],
- pressure: Inputs.getPressure(e),
- shiftKey,
- ctrlKey,
- metaKey: Utils.isDarwin() ? metaKey : ctrlKey,
- altKey,
- spaceKey: this.keys[' '],
- }
-
- this.pointer = info
-
- return info
- }
-
- pointerEnter<T extends string>(
- e: PointerEvent | React.PointerEvent,
- target: T
- ): TLPointerInfo<T> {
- const { shiftKey, ctrlKey, metaKey, altKey } = e
-
- const point = Inputs.getPoint(e, this.bounds)
-
- const info: TLPointerInfo<T> = {
- target,
- pointerId: e.pointerId,
- origin: point,
- delta: [0, 0],
- point: point,
- pressure: Inputs.getPressure(e),
- shiftKey,
- ctrlKey,
- metaKey: Utils.isDarwin() ? metaKey : ctrlKey,
- altKey,
- spaceKey: this.keys[' '],
- }
-
- this.pointer = info
-
- return info
- }
-
- pointerMove<T extends string>(e: PointerEvent | React.PointerEvent, target: T): TLPointerInfo<T> {
- const { shiftKey, ctrlKey, metaKey, altKey } = e
-
- const prev = this.pointer
-
- const point = Inputs.getPoint(e, this.bounds)
-
- const delta = prev?.point ? Vec.sub(point, prev.point) : [0, 0]
-
- const info: TLPointerInfo<T> = {
- origin: point,
- ...prev,
- target,
- pointerId: e.pointerId,
- point,
- delta,
- pressure: Inputs.getPressure(e),
- shiftKey,
- ctrlKey,
- metaKey: Utils.isDarwin() ? metaKey : ctrlKey,
- altKey,
- spaceKey: this.keys[' '],
- }
-
- this.pointer = info
-
- return info
- }
-
- pointerUp<T extends string>(e: PointerEvent | React.PointerEvent, target: T): TLPointerInfo<T> {
- const { shiftKey, ctrlKey, metaKey, altKey } = e
-
- const prev = this.pointer
-
- const point = Inputs.getPoint(e, this.bounds)
-
- const delta = prev?.point ? Vec.sub(point, prev.point) : [0, 0]
-
- this.activePointer = undefined
-
- const info: TLPointerInfo<T> = {
- origin: point,
- ...prev,
- target,
- pointerId: e.pointerId,
- point,
- delta,
- pressure: Inputs.getPressure(e),
- shiftKey,
- ctrlKey,
- metaKey: Utils.isDarwin() ? metaKey : ctrlKey,
- altKey,
- spaceKey: this.keys[' '],
- }
-
- this.pointer = info
-
- this.pointerUpTime = Date.now()
-
- return info
- }
-
- panStart = (e: WheelEvent): TLPointerInfo<'wheel'> => {
- const { shiftKey, ctrlKey, metaKey, altKey } = e
-
- const info: TLPointerInfo<'wheel'> = {
- target: 'wheel',
- pointerId: this.pointer?.pointerId || 0,
- origin: this.pointer?.origin || [0, 0],
- delta: [0, 0],
- pressure: 0.5,
- point: Inputs.getPoint(e, this.bounds),
- shiftKey,
- ctrlKey,
- metaKey,
- altKey,
- spaceKey: this.keys[' '],
- }
-
- this.pointer = info
-
- return info
- }
-
- pan = (delta: number[], e: WheelEvent): TLPointerInfo<'wheel'> => {
- if (!this.pointer || this.pointer.target !== 'wheel') {
- return this.panStart(e)
- }
-
- const { shiftKey, ctrlKey, metaKey, altKey } = e
-
- const prev = this.pointer
-
- const point = Inputs.getPoint(e, this.bounds)
-
- const info: TLPointerInfo<'wheel'> = {
- ...prev,
- target: 'wheel',
- delta,
- point,
- shiftKey,
- ctrlKey,
- metaKey,
- altKey,
- spaceKey: this.keys[' '],
- }
-
- this.pointer = info
-
- return info
- }
-
- isDoubleClick() {
- if (!this.pointer) return false
-
- const { origin, point } = this.pointer
-
- return Date.now() - this.pointerUpTime < DOUBLE_CLICK_DURATION && Vec.dist(origin, point) < 4
- }
-
- clear() {
- this.pointer = undefined
- }
-
- resetDoubleClick() {
- this.pointerUpTime = 0
- }
-
- keydown = (e: KeyboardEvent | React.KeyboardEvent): TLKeyboardInfo => {
- const { shiftKey, ctrlKey, metaKey, altKey } = e
-
- this.keys[e.key] = true
-
- return {
- point: this.pointer?.point || [0, 0],
- origin: this.pointer?.origin || [0, 0],
- key: e.key,
- keys: Object.keys(this.keys),
- shiftKey,
- ctrlKey,
- metaKey: Utils.isDarwin() ? metaKey : ctrlKey,
- altKey,
- }
- }
-
- keyup = (e: KeyboardEvent | React.KeyboardEvent): TLKeyboardInfo => {
- const { shiftKey, ctrlKey, metaKey, altKey } = e
-
- delete this.keys[e.key]
-
- return {
- point: this.pointer?.point || [0, 0],
- origin: this.pointer?.origin || [0, 0],
- key: e.key,
- keys: Object.keys(this.keys),
- shiftKey,
- ctrlKey,
- metaKey: Utils.isDarwin() ? metaKey : ctrlKey,
- altKey,
- }
- }
-
- pinch(point: number[], origin: number[]) {
- const { shiftKey, ctrlKey, metaKey, altKey } = this.keys
-
- const delta = Vec.sub(origin, point)
-
- const info: TLPointerInfo<'pinch'> = {
- pointerId: 0,
- target: 'pinch',
- origin,
- delta: delta,
- point: Vec.sub(Vec.round(point), [this.bounds.minX, this.bounds.minY]),
- pressure: 0.5,
- shiftKey,
- ctrlKey,
- metaKey: Utils.isDarwin() ? metaKey : ctrlKey,
- altKey,
- spaceKey: this.keys[' '],
- }
-
- this.pointer = info
-
- return info
- }
-
- reset() {
- this.pointerUpTime = 0
- this.pointer = undefined
- this.keyboard = undefined
- this.activePointer = undefined
- this.keys = {}
- }
-
- static getPoint(
- e: PointerEvent | React.PointerEvent | Touch | React.Touch | WheelEvent,
- bounds: TLBounds
- ): number[] {
- return [+e.clientX.toFixed(2) - bounds.minX, +e.clientY.toFixed(2) - bounds.minY]
- }
-
- static getPressure(e: PointerEvent | React.PointerEvent | Touch | React.Touch | WheelEvent) {
- return 'pressure' in e ? +e.pressure.toFixed(2) || 0.5 : 0.5
- }
-
- static commandKey(): string {
- return Utils.isDarwin() ? '⌘' : 'Ctrl'
- }
- }
-
- export const inputs = new Inputs()
|