@leafer-ui/interaction-web 1.0.0-rc.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023-present, Chao (Leafer) Wan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # @leafer-ui/interaction-web
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@leafer-ui/interaction-web",
3
+ "version": "1.0.0-rc.10",
4
+ "description": "@leafer-ui/interaction-web",
5
+ "author": "Chao (Leafer) Wan",
6
+ "license": "MIT",
7
+ "main": "src/index.ts",
8
+ "types": "types/index.d.ts",
9
+ "files": [
10
+ "src",
11
+ "types",
12
+ "dist"
13
+ ],
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/leaferjs/ui.git"
17
+ },
18
+ "homepage": "https://github.com/leaferjs/ui/tree/main/packages/interaction/interaction-web",
19
+ "bugs": "https://github.com/leaferjs/ui/issues",
20
+ "keywords": [
21
+ "leafer-ui",
22
+ "leaferjs"
23
+ ],
24
+ "dependencies": {
25
+ "@leafer-ui/core": "1.0.0-rc.10"
26
+ },
27
+ "devDependencies": {
28
+ "@leafer/interface": "1.0.0-rc.10"
29
+ }
30
+ }
@@ -0,0 +1,366 @@
1
+ import { IObject, IPointData, ITimer, IKeepTouchData, ICursorType } from '@leafer/interface'
2
+ import { MathHelper, InteractionBase, InteractionHelper, Cursor } from '@leafer-ui/core'
3
+
4
+ import { PointerEventHelper } from './PointerEventHelper'
5
+ import { WheelEventHelper } from './WheelEventHelper'
6
+ import { KeyEventHelper } from './KeyEventHelper'
7
+
8
+
9
+ interface IClientPoint {
10
+ clientX: number
11
+ clientY: number
12
+ }
13
+
14
+ interface IGestureEvent extends IClientPoint, UIEvent {
15
+ scale: number
16
+ rotation: number
17
+ preventDefault(): void
18
+ }
19
+
20
+
21
+ const { getMoveEventData, getZoomEventData, getRotateEventData } = InteractionHelper
22
+
23
+ export class Interaction extends InteractionBase {
24
+
25
+ protected view: HTMLElement
26
+
27
+ protected viewEvents: IObject
28
+ protected windowEvents: IObject
29
+
30
+ protected usePointer: boolean
31
+ protected useMultiTouch: boolean
32
+ protected useTouch: boolean
33
+
34
+ protected touchTimer: ITimer
35
+ protected touches?: Touch[]
36
+ protected lastGestureScale: number
37
+ protected lastGestureRotation: number
38
+
39
+ protected __listenEvents(): void {
40
+ super.__listenEvents()
41
+
42
+ const view = this.view = this.canvas.view as HTMLCanvasElement
43
+
44
+ // PointerEvent > TouchEvent > MouseEvent
45
+ this.viewEvents = {
46
+ 'pointerdown': this.onPointerDown,
47
+ 'mousedown': this.onMouseDown,
48
+ 'touchstart': this.onTouchStart,
49
+
50
+ 'contextmenu': this.onContextMenu,
51
+
52
+ 'wheel': this.onWheel,
53
+ 'gesturestart': this.onGesturestart,
54
+ 'gesturechange': this.onGesturechange,
55
+ 'gestureend': this.onGestureend
56
+ }
57
+
58
+ this.windowEvents = {
59
+ 'pointermove': this.onPointerMove,
60
+ 'pointerup': this.onPointerUp,
61
+ 'pointercancel': this.onPointerCancel,
62
+
63
+ 'mousemove': this.onMouseMove,
64
+ 'mouseup': this.onMouseUp,
65
+
66
+ // touch / multitouch
67
+ 'touchmove': this.onTouchMove,
68
+ 'touchend': this.onTouchEnd,
69
+ 'touchcancel': this.onTouchCancel,
70
+
71
+ 'keydown': this.onKeyDown,
72
+ 'keyup': this.onKeyUp,
73
+
74
+ 'scroll': this.onScroll
75
+ }
76
+
77
+ const { viewEvents, windowEvents } = this
78
+
79
+ for (let name in viewEvents) {
80
+ viewEvents[name] = viewEvents[name].bind(this)
81
+ view.addEventListener(name, viewEvents[name])
82
+ }
83
+
84
+ for (let name in windowEvents) {
85
+ windowEvents[name] = windowEvents[name].bind(this)
86
+ window.addEventListener(name, windowEvents[name])
87
+ }
88
+ }
89
+
90
+ protected __removeListenEvents(): void {
91
+ super.__removeListenEvents()
92
+
93
+ const { viewEvents, windowEvents } = this
94
+
95
+ for (let name in viewEvents) {
96
+ this.view.removeEventListener(name, viewEvents[name])
97
+ this.viewEvents = {}
98
+ }
99
+
100
+ for (let name in windowEvents) {
101
+ window.removeEventListener(name, windowEvents[name])
102
+ this.windowEvents = {}
103
+ }
104
+ }
105
+
106
+ protected getLocal(p: IClientPoint, updateClient?: boolean): IPointData {
107
+ if (updateClient) this.canvas.updateClientBounds()
108
+ const { clientBounds } = this.canvas
109
+ return { x: p.clientX - clientBounds.x, y: p.clientY - clientBounds.y }
110
+ }
111
+
112
+ protected getTouches(touches: TouchList): Touch[] {
113
+ const list: Touch[] = []
114
+ for (let i = 0, len = touches.length; i < len; i++) {
115
+ list.push(touches[i])
116
+ }
117
+ return list
118
+ }
119
+
120
+
121
+ protected preventDefaultPointer(e: UIEvent): void {
122
+ const { pointer } = this.config
123
+ if (pointer.preventDefault) e.preventDefault()
124
+ }
125
+
126
+ protected preventDefaultWheel(e: UIEvent): void {
127
+ const { wheel } = this.config
128
+ if (wheel.preventDefault) e.preventDefault()
129
+ }
130
+
131
+ protected preventWindowPointer(e: UIEvent) {
132
+ return !this.downData && e.target !== this.view
133
+ }
134
+
135
+ // key
136
+ protected onKeyDown(e: KeyboardEvent): void {
137
+ this.keyDown(KeyEventHelper.convert(e))
138
+ }
139
+
140
+ protected onKeyUp(e: KeyboardEvent): void {
141
+ this.keyUp(KeyEventHelper.convert(e))
142
+ }
143
+
144
+ // context menu
145
+
146
+ protected onContextMenu(e: PointerEvent): void {
147
+ if (this.config.pointer.preventDefaultMenu) e.preventDefault()
148
+ this.menu(PointerEventHelper.convert(e, this.getLocal(e)))
149
+ }
150
+
151
+ protected onScroll(): void {
152
+ this.canvas.updateClientBounds()
153
+ }
154
+
155
+ // pointer
156
+ protected onPointerDown(e: PointerEvent): void {
157
+ this.preventDefaultPointer(e)
158
+
159
+ this.usePointer || (this.usePointer = true)
160
+ if (this.useMultiTouch) return
161
+ this.pointerDown(PointerEventHelper.convert(e, this.getLocal(e)))
162
+ }
163
+
164
+ protected onPointerMove(e: PointerEvent): void {
165
+ this.usePointer || (this.usePointer = true)
166
+ if (this.useMultiTouch || this.preventWindowPointer(e)) return
167
+ this.pointerMove(PointerEventHelper.convert(e, this.getLocal(e, true)))
168
+ }
169
+
170
+ protected onPointerUp(e: PointerEvent): void {
171
+ if (this.downData) this.preventDefaultPointer(e)
172
+ if (this.useMultiTouch || this.preventWindowPointer(e)) return
173
+ this.pointerUp(PointerEventHelper.convert(e, this.getLocal(e)))
174
+ }
175
+
176
+ protected onPointerCancel(): void {
177
+ if (this.useMultiTouch) return
178
+ this.pointerCancel()
179
+ }
180
+
181
+
182
+ // mouse
183
+ protected onMouseDown(e: MouseEvent): void {
184
+ this.preventDefaultPointer(e)
185
+
186
+ if (this.useTouch || this.usePointer) return
187
+ this.pointerDown(PointerEventHelper.convertMouse(e, this.getLocal(e)))
188
+ }
189
+
190
+ protected onMouseMove(e: MouseEvent): void {
191
+ if (this.useTouch || this.usePointer || this.preventWindowPointer(e)) return
192
+ this.pointerMove(PointerEventHelper.convertMouse(e, this.getLocal(e, true)))
193
+ }
194
+
195
+ protected onMouseUp(e: MouseEvent): void {
196
+ if (this.downData) this.preventDefaultPointer(e)
197
+ if (this.useTouch || this.usePointer || this.preventWindowPointer(e)) return
198
+ this.pointerUp(PointerEventHelper.convertMouse(e, this.getLocal(e)))
199
+ }
200
+
201
+ protected onMouseCancel(): void {
202
+ if (this.useTouch || this.usePointer) return
203
+ this.pointerCancel()
204
+ }
205
+
206
+
207
+ // touch
208
+ protected onTouchStart(e: TouchEvent): void {
209
+ e.preventDefault()
210
+
211
+ this.multiTouchStart(e)
212
+
213
+ if (this.usePointer) return
214
+ if (this.touchTimer) {
215
+ window.clearTimeout(this.touchTimer)
216
+ this.touchTimer = 0
217
+ }
218
+ this.useTouch = true
219
+ const touch = PointerEventHelper.getTouch(e)
220
+ this.pointerDown(PointerEventHelper.convertTouch(e, this.getLocal(touch, true)))
221
+ }
222
+
223
+ protected onTouchMove(e: TouchEvent): void {
224
+ this.multiTouchMove(e)
225
+
226
+ if (this.usePointer || this.preventWindowPointer(e)) return
227
+ const touch = PointerEventHelper.getTouch(e)
228
+ this.pointerMove(PointerEventHelper.convertTouch(e, this.getLocal(touch)))
229
+ }
230
+
231
+ protected onTouchEnd(e: TouchEvent): void {
232
+ this.multiTouchEnd()
233
+
234
+ if (this.usePointer || this.preventWindowPointer(e)) return
235
+ if (this.touchTimer) clearTimeout(this.touchTimer)
236
+ this.touchTimer = setTimeout(() => {
237
+ this.useTouch = false
238
+ }, 500) // stop touch > mouse
239
+ const touch = PointerEventHelper.getTouch(e)
240
+ this.pointerUp(PointerEventHelper.convertTouch(e, this.getLocal(touch)))
241
+ }
242
+
243
+ protected onTouchCancel(): void {
244
+ if (this.usePointer) return
245
+ this.pointerCancel()
246
+ }
247
+
248
+
249
+ // multiTouch
250
+ protected multiTouchStart(e: TouchEvent): void {
251
+ this.useMultiTouch = (e.touches.length >= 2)
252
+ this.touches = this.useMultiTouch ? this.getTouches(e.touches) : undefined
253
+ if (this.useMultiTouch) this.pointerCancel()
254
+ }
255
+
256
+ protected multiTouchMove(e: TouchEvent): void {
257
+ if (!this.useMultiTouch) return
258
+ if (e.touches.length > 1) {
259
+ const touches = this.getTouches(e.touches)
260
+ const list = this.getKeepTouchList(this.touches, touches)
261
+ if (list.length > 1) {
262
+ this.multiTouch(InteractionHelper.getBase(e), list)
263
+ this.touches = touches
264
+ }
265
+ }
266
+ }
267
+
268
+ protected multiTouchEnd(): void {
269
+ this.touches = null
270
+ this.useMultiTouch = false
271
+ this.transformEnd()
272
+ }
273
+
274
+ protected getKeepTouchList(old: Touch[], touches: Touch[]): IKeepTouchData[] {
275
+ let to: Touch
276
+ const list: IKeepTouchData[] = []
277
+ old.forEach(from => {
278
+ to = touches.find(touch => touch.identifier === from.identifier)
279
+ if (to) list.push({ from: this.getLocal(from), to: this.getLocal(to) })
280
+ })
281
+ return list
282
+ }
283
+
284
+ protected getLocalTouchs(points: Touch[]): IPointData[] {
285
+ return points.map(point => this.getLocal(point))
286
+ }
287
+
288
+
289
+ // wheel
290
+ protected onWheel(e: WheelEvent): void {
291
+ this.preventDefaultWheel(e)
292
+
293
+ const { wheel } = this.config
294
+ const scale = wheel.getScale ? wheel.getScale(e, wheel) : WheelEventHelper.getScale(e, wheel)
295
+ const local = this.getLocal(e)
296
+
297
+ const eventBase = InteractionHelper.getBase(e)
298
+ scale !== 1 ? this.zoom(getZoomEventData(local, scale, eventBase)) : this.move(getMoveEventData(local, wheel.getMove ? wheel.getMove(e, wheel) : WheelEventHelper.getMove(e, wheel), eventBase))
299
+ }
300
+
301
+
302
+ // safari
303
+ protected onGesturestart(e: IGestureEvent): void {
304
+ this.preventDefaultWheel(e)
305
+
306
+ this.lastGestureScale = 1
307
+ this.lastGestureRotation = 0
308
+ }
309
+
310
+ protected onGesturechange(e: IGestureEvent): void {
311
+ this.preventDefaultWheel(e)
312
+
313
+ const local = this.getLocal(e)
314
+ const eventBase = InteractionHelper.getBase(e)
315
+ const changeScale = e.scale / this.lastGestureScale
316
+ const changeAngle = e.rotation - this.lastGestureRotation
317
+
318
+ let { rotateSpeed } = this.config.wheel
319
+ rotateSpeed = MathHelper.within(rotateSpeed, 0, 1)
320
+
321
+ this.zoom(getZoomEventData(local, changeScale * changeScale, eventBase))
322
+ this.rotate(getRotateEventData(local, changeAngle / Math.PI * 180 * (rotateSpeed / 4 + 0.1), eventBase))
323
+
324
+ this.lastGestureScale = e.scale
325
+ this.lastGestureRotation = e.rotation
326
+ }
327
+
328
+ protected onGestureend(e: IGestureEvent): void {
329
+ this.preventDefaultWheel(e)
330
+
331
+ this.transformEnd()
332
+ }
333
+
334
+
335
+ // cursor
336
+ public setCursor(cursor: ICursorType | ICursorType[]): void {
337
+ super.setCursor(cursor)
338
+ const list: ICursorType[] = []
339
+ this.eachCursor(cursor, list)
340
+ if (typeof list[list.length - 1] === 'object') list.push('default')
341
+ this.canvas.view.style.cursor = list.map(item => (typeof item === 'object') ? `url(${item.url}) ${item.x || 0} ${item.y || 0}` : item).join(',')
342
+ }
343
+
344
+ protected eachCursor(cursor: ICursorType | ICursorType[], list: ICursorType[], level = 0): void {
345
+ level++
346
+ if (cursor instanceof Array) {
347
+ cursor.forEach(item => this.eachCursor(item, list, level))
348
+ } else {
349
+ const custom = typeof cursor === 'string' && Cursor.get(cursor)
350
+ if (custom && level < 2) {
351
+ this.eachCursor(custom, list, level)
352
+ } else {
353
+ list.push(cursor)
354
+ }
355
+ }
356
+ }
357
+
358
+ public destroy(): void {
359
+ if (this.view) {
360
+ super.destroy()
361
+ this.view = null
362
+ this.touches = null
363
+ }
364
+ }
365
+
366
+ }
@@ -0,0 +1,17 @@
1
+ import { IKeyEvent } from '@leafer/interface'
2
+ import { InteractionHelper } from '@leafer-ui/core'
3
+
4
+
5
+ export const KeyEventHelper = {
6
+
7
+ convert(e: KeyboardEvent): IKeyEvent {
8
+ const base = InteractionHelper.getBase(e)
9
+ const data: IKeyEvent = {
10
+ ...base,
11
+ code: e.code,
12
+ key: e.key
13
+ }
14
+ return data
15
+ }
16
+
17
+ }
@@ -0,0 +1,59 @@
1
+ import { IPointData, IPointerEvent, PointerType } from '@leafer/interface'
2
+ import { InteractionHelper } from '@leafer-ui/core'
3
+
4
+
5
+ export const PointerEventHelper = {
6
+
7
+ convert(e: PointerEvent, local: IPointData): IPointerEvent {
8
+ const base = InteractionHelper.getBase(e)
9
+ const data: IPointerEvent = {
10
+ ...base,
11
+ x: local.x,
12
+ y: local.y,
13
+ width: e.width,
14
+ height: e.height,
15
+ pointerType: e.pointerType as PointerType,
16
+ pressure: e.pressure,
17
+ }
18
+
19
+ if (data.pointerType === 'pen') {
20
+ data.tangentialPressure = e.tangentialPressure
21
+ data.tiltX = e.tiltX
22
+ data.tiltY = e.tiltY
23
+ data.twist = e.twist
24
+ }
25
+ return data
26
+ },
27
+
28
+ convertMouse(e: MouseEvent, local: IPointData): IPointerEvent {
29
+ const base = InteractionHelper.getBase(e)
30
+ return {
31
+ ...base,
32
+ x: local.x,
33
+ y: local.y,
34
+ width: 1,
35
+ height: 1,
36
+ pointerType: 'mouse',
37
+ pressure: 0.5,
38
+ }
39
+ },
40
+
41
+ convertTouch(e: TouchEvent, local: IPointData): IPointerEvent {
42
+ const touch = PointerEventHelper.getTouch(e)
43
+ const base = InteractionHelper.getBase(e)
44
+ return {
45
+ ...base,
46
+ x: local.x,
47
+ y: local.y,
48
+ width: 1,
49
+ height: 1,
50
+ pointerType: 'touch',
51
+ pressure: touch.force,
52
+ }
53
+ },
54
+
55
+ getTouch(e: TouchEvent): Touch {
56
+ return e.targetTouches[0] || e.changedTouches[0]
57
+ }
58
+
59
+ }
@@ -0,0 +1,47 @@
1
+ import { IPointData, IWheelConfig } from '@leafer/interface'
2
+ import { MathHelper, Platform } from '@leafer-ui/core'
3
+
4
+
5
+ export const WheelEventHelper = {
6
+
7
+ getMove(e: WheelEvent, config: IWheelConfig): IPointData {
8
+ let { moveSpeed } = config
9
+ let { deltaX, deltaY } = e
10
+ if (e.shiftKey && !deltaX) { // Window
11
+ deltaX = deltaY
12
+ deltaY = 0
13
+ }
14
+ if (deltaX > 50) deltaX = Math.max(50, deltaX / 3)
15
+ if (deltaY > 50) deltaY = Math.max(50, deltaY / 3)
16
+ return { x: -deltaX * moveSpeed * 2, y: -deltaY * moveSpeed * 2 }
17
+ },
18
+
19
+ getScale(e: WheelEvent, config: IWheelConfig): number {
20
+
21
+ let zoom: boolean
22
+ let scale = 1
23
+ let { zoomMode, zoomSpeed } = config
24
+
25
+ const delta = e.deltaY || e.deltaX
26
+
27
+ if (zoomMode) {
28
+ // mac 触摸板滚动手势的deltaY是整数, 鼠标滚动/触摸板缩放的deltaY有小数点, firfox鼠标滚动为整数,为18或19的倍数
29
+ // windows 始终是整数
30
+ zoom = (zoomMode === 'mouse') ? true : (!e.deltaX && (Platform.intWheelDeltaY ? Math.abs(delta) > 17 : Math.ceil(delta) !== delta))
31
+ if (e.shiftKey || e.metaKey || e.ctrlKey) zoom = true
32
+ } else {
33
+ zoom = !e.shiftKey && (e.metaKey || e.ctrlKey)
34
+ }
35
+
36
+ if (zoom) {
37
+ zoomSpeed = MathHelper.within(zoomSpeed, 0, 1)
38
+ const min = e.deltaY ? config.delta.y : config.delta.x
39
+ scale = 1 - delta / (min * 4) * zoomSpeed // zoomSpeed
40
+ if (scale < 0.5) scale = 0.5
41
+ if (scale >= 1.5) scale = 1.5
42
+ }
43
+
44
+ return scale
45
+ }
46
+
47
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export { Interaction } from './Interaction'
@@ -0,0 +1,61 @@
1
+ import { IObject, ITimer, IPointData, IKeepTouchData, ICursorType } from '@leafer/interface';
2
+ import { InteractionBase } from '@leafer-ui/core';
3
+
4
+ interface IClientPoint {
5
+ clientX: number;
6
+ clientY: number;
7
+ }
8
+ interface IGestureEvent extends IClientPoint, UIEvent {
9
+ scale: number;
10
+ rotation: number;
11
+ preventDefault(): void;
12
+ }
13
+ declare class Interaction extends InteractionBase {
14
+ protected view: HTMLElement;
15
+ protected viewEvents: IObject;
16
+ protected windowEvents: IObject;
17
+ protected usePointer: boolean;
18
+ protected useMultiTouch: boolean;
19
+ protected useTouch: boolean;
20
+ protected touchTimer: ITimer;
21
+ protected touches?: Touch[];
22
+ protected lastGestureScale: number;
23
+ protected lastGestureRotation: number;
24
+ protected __listenEvents(): void;
25
+ protected __removeListenEvents(): void;
26
+ protected getLocal(p: IClientPoint, updateClient?: boolean): IPointData;
27
+ protected getTouches(touches: TouchList): Touch[];
28
+ protected preventDefaultPointer(e: UIEvent): void;
29
+ protected preventDefaultWheel(e: UIEvent): void;
30
+ protected preventWindowPointer(e: UIEvent): boolean;
31
+ protected onKeyDown(e: KeyboardEvent): void;
32
+ protected onKeyUp(e: KeyboardEvent): void;
33
+ protected onContextMenu(e: PointerEvent): void;
34
+ protected onScroll(): void;
35
+ protected onPointerDown(e: PointerEvent): void;
36
+ protected onPointerMove(e: PointerEvent): void;
37
+ protected onPointerUp(e: PointerEvent): void;
38
+ protected onPointerCancel(): void;
39
+ protected onMouseDown(e: MouseEvent): void;
40
+ protected onMouseMove(e: MouseEvent): void;
41
+ protected onMouseUp(e: MouseEvent): void;
42
+ protected onMouseCancel(): void;
43
+ protected onTouchStart(e: TouchEvent): void;
44
+ protected onTouchMove(e: TouchEvent): void;
45
+ protected onTouchEnd(e: TouchEvent): void;
46
+ protected onTouchCancel(): void;
47
+ protected multiTouchStart(e: TouchEvent): void;
48
+ protected multiTouchMove(e: TouchEvent): void;
49
+ protected multiTouchEnd(): void;
50
+ protected getKeepTouchList(old: Touch[], touches: Touch[]): IKeepTouchData[];
51
+ protected getLocalTouchs(points: Touch[]): IPointData[];
52
+ protected onWheel(e: WheelEvent): void;
53
+ protected onGesturestart(e: IGestureEvent): void;
54
+ protected onGesturechange(e: IGestureEvent): void;
55
+ protected onGestureend(e: IGestureEvent): void;
56
+ setCursor(cursor: ICursorType | ICursorType[]): void;
57
+ protected eachCursor(cursor: ICursorType | ICursorType[], list: ICursorType[], level?: number): void;
58
+ destroy(): void;
59
+ }
60
+
61
+ export { Interaction };