Przeglądaj źródła

fix: pinching state for tools

Peng Xiao 3 lat temu
rodzic
commit
fda26c291f

+ 2 - 2
tldraw/packages/core/src/lib/tools/TLBoxTool/states/IdleState.tsx

@@ -17,8 +17,8 @@ export class IdleState<
   }
 
   onPinchStart: TLStateEvents<S, K>['onPinchStart'] = (...args) => {
-    this.app.transition('select', { returnTo: 'box' })
-    this.app.onPinchStart?.(...args)
+    this.app.transition('select', { returnTo: this.app.currentState.id })
+    this.app._events.onPinchStart?.(...args)
   }
 
   onKeyDown: TLStateEvents<S>['onKeyDown'] = (info, e) => {

+ 2 - 2
tldraw/packages/core/src/lib/tools/TLDotTool/states/IdleState.tsx

@@ -17,8 +17,8 @@ export class IdleState<
   }
 
   onPinchStart: TLStateEvents<S, K>['onPinchStart'] = (...args) => {
-    this.app.transition('select', { returnTo: 'box' })
-    this.app.onPinchStart?.(...args)
+    this.app.transition('select', { returnTo: this.app.currentState.id })
+    this.app._events.onPinchStart?.(...args)
   }
 
   onKeyDown: TLStateEvents<S>['onKeyDown'] = (info, e) => {

+ 1 - 1
tldraw/packages/core/src/lib/tools/TLDrawTool/states/IdleState.tsx

@@ -17,7 +17,7 @@ export class IdleState<
   }
 
   onPinchStart: TLStateEvents<S, K>['onPinchStart'] = (...args) => {
-    this.app.transition('select', { returnTo: 'draw' })
+    this.app.transition('select', { returnTo: this.app.currentState.id })
     this.app._events.onPinchStart?.(...args)
   }
 

+ 2 - 2
tldraw/packages/core/src/lib/tools/TLEraseTool/states/IdleState.tsx

@@ -16,8 +16,8 @@ export class IdleState<
   }
 
   onPinchStart: TLStateEvents<S, K>['onPinchStart'] = (...args) => {
-    this.app.transition('select', { returnTo: 'draw' })
-    this.app.onPinchStart?.(...args)
+    this.app.transition('select', { returnTo: this.app.currentState.id })
+    this.app._events.onPinchStart?.(...args)
   }
 
   onKeyDown: TLStateEvents<S>['onKeyDown'] = (info, e) => {

+ 2 - 2
tldraw/packages/core/src/lib/tools/TLLineTool/states/IdleState.tsx

@@ -17,8 +17,8 @@ export class IdleState<
   }
 
   onPinchStart: TLStateEvents<S, K>['onPinchStart'] = (...args) => {
-    this.app.transition('select', { returnTo: 'Line' })
-    this.app.onPinchStart?.(...args)
+    this.app.transition('select', { returnTo: this.app.currentState.id })
+    this.app._events.onPinchStart?.(...args)
   }
 
   onKeyDown: TLStateEvents<S>['onKeyDown'] = (info, e) => {

+ 12 - 3
tldraw/packages/core/src/lib/tools/TLMoveTool/TLMoveTool.ts

@@ -1,6 +1,6 @@
 import { TLApp, TLShape, TLTool } from '~lib'
-import { TLCursor, TLEventMap } from '~types'
-import { IdleHoldState, IdleState, PanningState } from './states'
+import { TLCursor, TLEventMap, TLStateEvents } from '~types'
+import { IdleHoldState, IdleState, PanningState, PinchingState } from './states'
 
 export class TLMoveTool<
   S extends TLShape = TLShape,
@@ -10,7 +10,7 @@ export class TLMoveTool<
   static id = 'move'
   static shortcut = ['h']
 
-  static states = [IdleState, IdleHoldState, PanningState]
+  static states = [IdleState, IdleHoldState, PanningState, PinchingState]
 
   static initial = 'idle'
 
@@ -21,4 +21,13 @@ export class TLMoveTool<
   onEnter = (info: any) => {
     this.prevTool = info?.prevTool
   }
+
+  onKeyDown: TLStateEvents<S>['onKeyDown'] = (info, e) => {
+    switch (e.key) {
+      case 'Escape': {
+        this.app.transition('select')
+        break
+      }
+    }
+  }
 }

+ 5 - 1
tldraw/packages/core/src/lib/tools/TLMoveTool/states/IdleHoldState.tsx

@@ -1,5 +1,5 @@
 import { TLApp, TLShape, TLToolState } from '~lib'
-import type { TLEventMap, TLStateEvents } from '~types'
+import type { TLEventMap, TLEvents, TLStateEvents } from '~types'
 import type { TLMoveTool } from '../TLMoveTool'
 
 export class IdleHoldState<
@@ -14,4 +14,8 @@ export class IdleHoldState<
     if (info.order) return
     this.tool.transition('panning', { prevState: 'idleHold' })
   }
+
+  onPinchStart: TLEvents<S>['pinch'] = (info, event) => {
+    this.tool.transition('pinching', { info, event })
+  }
 }

+ 5 - 1
tldraw/packages/core/src/lib/tools/TLMoveTool/states/IdleState.tsx

@@ -1,5 +1,5 @@
 import { TLApp, TLShape, TLToolState } from '~lib'
-import type { TLEventMap, TLStateEvents } from '~types'
+import type { TLEventMap, TLEvents, TLStateEvents } from '~types'
 import type { TLMoveTool } from '../TLMoveTool'
 
 export class IdleState<
@@ -20,6 +20,10 @@ export class IdleState<
     }
   }
 
+  onPinchStart: TLEvents<S>['pinch'] = (info, event) => {
+    this.tool.transition('pinching', { info, event })
+  }
+
   onPointerDown: TLStateEvents<S, K>['onPointerDown'] = (info, e) => {
     if (info.order) return
     this.tool.transition('panning')

+ 46 - 0
tldraw/packages/core/src/lib/tools/TLMoveTool/states/PinchingState.ts

@@ -0,0 +1,46 @@
+import { Vec } from '@tldraw/vec'
+import { TLApp, TLMoveTool, TLShape, TLToolState } from '~lib'
+import type { TLEventInfo, TLEventMap, TLEvents } from '~types'
+
+type GestureInfo<
+  S extends TLShape,
+  K extends TLEventMap,
+  E extends TLEventInfo<S> = TLEventInfo<S>
+> = {
+  info: E & { delta: number[]; point: number[]; offset: number[] }
+  event: K['wheel'] | K['pointer'] | K['touch'] | K['keyboard'] | K['gesture']
+}
+
+export class PinchingState<
+  S extends TLShape,
+  K extends TLEventMap,
+  R extends TLApp<S, K>,
+  P extends TLMoveTool<S, K, R>
+> extends TLToolState<S, K, R, P> {
+  static id = 'pinching'
+
+  private origin: number[] = [0, 0]
+
+  private prevDelta: number[] = [0, 0]
+
+  private pinchCamera(point: number[], delta: number[], zoom: number) {
+    const { camera } = this.app.viewport
+    const nextPoint = Vec.sub(camera.point, Vec.div(delta, camera.zoom))
+    const p0 = Vec.sub(Vec.div(point, camera.zoom), nextPoint)
+    const p1 = Vec.sub(Vec.div(point, zoom), nextPoint)
+    this.app.setCamera(Vec.toFixed(Vec.add(nextPoint, Vec.sub(p1, p0))), zoom)
+  }
+
+  onEnter = (info: GestureInfo<S, K>) => {
+    this.prevDelta = info.info.delta
+    this.origin = info.info.point
+  }
+
+  onPinch: TLEvents<S>['pinch'] = info => {
+    this.pinchCamera(info.point, [0, 0], info.offset[0])
+  }
+
+  onPinchEnd: TLEvents<S>['pinch'] = () => {
+    this.tool.transition('idle')
+  }
+}

+ 1 - 0
tldraw/packages/core/src/lib/tools/TLMoveTool/states/index.ts

@@ -1,3 +1,4 @@
 export * from './PanningState'
 export * from './IdleState'
 export * from './IdleHoldState'
+export * from './PinchingState'

+ 6 - 0
tldraw/packages/core/src/lib/tools/TLSelectTool/TLSelectTool.tsx

@@ -53,4 +53,10 @@ export class TLSelectTool<
     PinchingState,
     EditingShapeState,
   ]
+
+  returnTo = ''
+
+  onEnter = (info: { fromId: string, returnTo: string } & any) => {
+    this.returnTo = info?.returnTo
+  }
 }

+ 3 - 3
tldraw/packages/core/src/lib/tools/TLSelectTool/states/IdleState.ts

@@ -11,9 +11,9 @@ export class IdleState<
   static id = 'idle'
 
   onEnter = (info: { fromId: string } & any) => {
-    // if (info.fromId === 'editingShape') {
-    //   this.onPointerDown(info as any, {} as any)
-    // }
+    if (info.fromId === 'pinching' && this.parent.returnTo) {
+      this.app.transition(this.parent.returnTo)
+    }
   }
 
   onExit = () => {

+ 2 - 2
tldraw/packages/core/src/lib/tools/TLTextTool/states/IdleState.tsx

@@ -17,8 +17,8 @@ export class IdleState<
   }
 
   onPinchStart: TLStateEvents<S, K>['onPinchStart'] = (...args) => {
-    this.app.transition('select', { returnTo: 'box' })
-    this.app.onPinchStart?.(...args)
+    this.app.transition('select', { returnTo: this.app.currentState.id })
+    this.app._events.onPinchStart?.(...args)
   }
 
   onKeyDown: TLStateEvents<S>['onKeyDown'] = (info, e) => {