@leafer-ui/interaction 1.0.0-rc.19 → 1.0.0-rc.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leafer-ui/interaction",
3
- "version": "1.0.0-rc.19",
3
+ "version": "1.0.0-rc.21",
4
4
  "description": "@leafer-ui/interaction",
5
5
  "author": "Chao (Leafer) Wan",
6
6
  "license": "MIT",
@@ -22,11 +22,12 @@
22
22
  "leaferjs"
23
23
  ],
24
24
  "dependencies": {
25
- "@leafer/core": "1.0.0-rc.19",
26
- "@leafer-ui/draw": "1.0.0-rc.19",
27
- "@leafer-ui/event": "1.0.0-rc.19"
25
+ "@leafer/core": "1.0.0-rc.21",
26
+ "@leafer-ui/draw": "1.0.0-rc.21",
27
+ "@leafer-ui/event": "1.0.0-rc.21"
28
28
  },
29
29
  "devDependencies": {
30
- "@leafer/interface": "1.0.0-rc.19"
30
+ "@leafer/interface": "1.0.0-rc.21",
31
+ "@leafer-ui/interface": "1.0.0-rc.21"
31
32
  }
32
33
  }
package/src/Dragger.ts CHANGED
@@ -56,7 +56,7 @@ export class Dragger {
56
56
  }
57
57
 
58
58
  if (!this.moving && canDrag) {
59
- if (this.moving = interaction.canMove(this.downData) || interaction.isHoldRightKey) interaction.emit(MoveEvent.START, this.dragData)
59
+ if (this.moving = interaction.canMove(this.downData) || interaction.isHoldRightKey || interaction.isMobileDragEmpty) interaction.emit(MoveEvent.START, this.dragData)
60
60
  }
61
61
 
62
62
  if (!this.moving) {
@@ -109,7 +109,7 @@ export class Dragger {
109
109
  const list = this.getList()
110
110
  if (list.length && running) {
111
111
  const { moveX, moveY } = this.dragData
112
- list.forEach(leaf => leaf.moveWorld(moveX, moveY))
112
+ list.forEach(leaf => leaf.draggable && leaf.moveWorld(moveX, moveY))
113
113
  }
114
114
  }
115
115
 
@@ -141,7 +141,7 @@ export class Dragger {
141
141
  }
142
142
 
143
143
  public dragEnd(data: IPointerEvent, speed?: number): void {
144
- if (!this.dragData) return
144
+ if (!this.dragging && !this.moving) return
145
145
 
146
146
  const { moveX, moveY } = this.dragData
147
147
  if (this.interaction.config.move.dragAnimate && this.canAnimate && this.moving && (Math.abs(moveX) > 1 || Math.abs(moveY) > 1)) {
@@ -165,12 +165,19 @@ export class Dragger {
165
165
  if (throughPath) endDragData.throughPath = throughPath
166
166
  endDragData.path = path
167
167
 
168
- if (this.moving) interaction.emit(MoveEvent.END, endDragData)
168
+ if (this.moving) {
169
+ this.moving = false
170
+ interaction.emit(MoveEvent.END, endDragData)
171
+ }
172
+
169
173
  if (this.dragging) {
174
+ const dropList = this.getList()
175
+
176
+ this.dragging = false
170
177
  interaction.emit(DragEvent.END, endDragData)
171
178
 
172
- this.swipe(data, endDragData)
173
- this.drop(data)
179
+ this.swipe(data, downData, dragData, endDragData)
180
+ this.drop(data, dropList, this.dragEnterPath)
174
181
  }
175
182
 
176
183
  this.autoMoveCancel()
@@ -185,24 +192,23 @@ export class Dragger {
185
192
  }
186
193
 
187
194
 
188
- protected swipe(data: IPointerEvent, endDragData: IDragEvent): void {
189
- const { interaction, downData } = this
195
+ protected swipe(data: IPointerEvent, downData: IPointerEvent, dragData: IDragEvent, endDragData: IDragEvent): void {
196
+ const { interaction } = this
190
197
  if (PointHelper.getDistance(downData, data) > interaction.config.pointer.swipeDistance) {
191
- const swipeData = getSwipeEventData(downData, this.dragData, endDragData)
198
+ const swipeData = getSwipeEventData(downData, dragData, endDragData)
192
199
  this.interaction.emit(swipeData.type, swipeData)
193
200
  }
194
201
  }
195
202
 
196
- protected drop(data: IPointerEvent): void {
197
- const dropData = getDropEventData(data, this.getList(), DragEvent.data)
198
- dropData.path = this.dragEnterPath
203
+ protected drop(data: IPointerEvent, dropList: ILeafList, dragEnterPath: ILeafList): void {
204
+ const dropData = getDropEventData(data, dropList, DragEvent.data)
205
+ dropData.path = dragEnterPath
199
206
  this.interaction.emit(DropEvent.DROP, dropData)
200
- this.interaction.emit(DragEvent.LEAVE, data, this.dragEnterPath)
207
+ this.interaction.emit(DragEvent.LEAVE, data, dragEnterPath)
201
208
  }
202
209
 
203
210
  protected dragReset(): void {
204
211
  DragEvent.list = DragEvent.data = this.dragableList = this.dragData = this.downData = this.dragOverPath = this.dragEnterPath = null
205
- this.dragging = this.moving = false
206
212
  }
207
213
 
208
214
 
@@ -1,28 +1,32 @@
1
- import { IScreenSizeData, IHitCanvasManager, ILeaf, IHitCanvas, ILeafList } from '@leafer/interface'
1
+ import { IHitCanvasManager, ILeaf, IHitCanvas, ILeafList, ILeaferCanvasConfig } from '@leafer/interface'
2
2
  import { CanvasManager, LeafList, Creator } from '@leafer/core'
3
3
 
4
4
 
5
5
  export class HitCanvasManager extends CanvasManager implements IHitCanvasManager {
6
6
 
7
- protected pathTypeList: ILeafList = new LeafList()
8
- protected imageTypeList: ILeafList = new LeafList()
7
+ public maxTotal = 1000 // 最多缓存多少张画布
9
8
 
10
- public getImageType(leaf: ILeaf, size: IScreenSizeData): IHitCanvas {
11
- this.imageTypeList.add(leaf)
12
- return Creator.hitCanvas(size)
9
+ protected pathList: ILeafList = new LeafList()
10
+ protected pixelList: ILeafList = new LeafList()
11
+
12
+ public getPixelType(leaf: ILeaf, config: ILeaferCanvasConfig): IHitCanvas {
13
+ this.__autoClear()
14
+ this.pixelList.add(leaf)
15
+ return Creator.hitCanvas(config)
13
16
  }
14
17
 
15
18
  public getPathType(leaf: ILeaf): IHitCanvas {
16
- this.pathTypeList.add(leaf)
19
+ this.__autoClear()
20
+ this.pathList.add(leaf)
17
21
  return Creator.hitCanvas()
18
22
  }
19
23
 
20
24
  public clearImageType(): void {
21
- this.__clearLeafList(this.imageTypeList)
25
+ this.__clearLeafList(this.pixelList)
22
26
  }
23
27
 
24
28
  public clearPathType(): void {
25
- this.__clearLeafList(this.pathTypeList)
29
+ this.__clearLeafList(this.pathList)
26
30
  }
27
31
 
28
32
  protected __clearLeafList(leafList: ILeafList): void {
@@ -37,6 +41,10 @@ export class HitCanvasManager extends CanvasManager implements IHitCanvasManager
37
41
  }
38
42
  }
39
43
 
44
+ protected __autoClear(): void {
45
+ if (this.pathList.length + this.pixelList.length > this.maxTotal) this.clear()
46
+ }
47
+
40
48
  public clear(): void {
41
49
  this.clearPathType()
42
50
  this.clearImageType()
@@ -1,6 +1,7 @@
1
1
  import { IUIEvent, IPointerEvent, ILeaf, IInteraction, IInteractionConfig, ILeafList, IMoveEvent, IZoomEvent, IRotateEvent, ISelector, IBounds, IEventListenerId, IInteractionCanvas, ITimer, IKeepTouchData, IKeyEvent, IPickOptions, ICursorType, IBooleanMap } from '@leafer/interface'
2
2
  import { LeaferEvent, ResizeEvent, LeafList, Bounds, PointHelper, DataHelper } from '@leafer/core'
3
3
 
4
+ import { IApp } from '@leafer-ui/interface'
4
5
  import { PointerEvent, DropEvent, KeyEvent, PointerButton, Keyboard } from '@leafer-ui/event'
5
6
 
6
7
  import { Transformer } from './Transformer'
@@ -21,9 +22,13 @@ export class InteractionBase implements IInteraction {
21
22
  public running: boolean
22
23
 
23
24
  public get dragging(): boolean { return this.dragger.dragging }
25
+ public get moveMode(): boolean { return this.config.move.drag || this.isHoldSpaceKey || this.isHoldMiddleKey || (this.isHoldRightKey && this.dragger.moving) || this.isDragEmpty }
26
+
24
27
  public get isDragEmpty(): boolean { return this.config.move.dragEmpty && this.isRootPath(this.hoverData) && (!this.downData || this.isRootPath(this.downData)) }
28
+ public get isMobileDragEmpty(): boolean { return this.config.move.dragEmpty && !this.config.pointer.hover && this.downData && this.isTreePath(this.downData) }
29
+ public get isHoldMiddleKey(): boolean { return this.config.move.holdMiddleKey && this.downData && PointerButton.middle(this.downData) }
25
30
  public get isHoldRightKey(): boolean { return this.config.move.holdRightKey && this.downData && PointerButton.right(this.downData) }
26
- public get moveMode(): boolean { return this.config.move.drag || (this.config.move.holdSpaceKey && Keyboard.isHoldSpaceKey()) || (this.downData && ((this.config.move.holdMiddleKey && PointerButton.middle(this.downData)) || (this.isHoldRightKey && this.dragger.moving))) || this.isDragEmpty }
31
+ public get isHoldSpaceKey(): boolean { return this.config.move.holdSpaceKey && Keyboard.isHoldSpaceKey() }
27
32
 
28
33
  public config: IInteractionConfig = config
29
34
 
@@ -103,7 +108,7 @@ export class InteractionBase implements IInteraction {
103
108
  }
104
109
 
105
110
  this.dragger.setDragData(data) // must after down event
106
- this.updateCursor(data)
111
+ if (!this.isHoldRightKey) this.updateCursor(data)
107
112
  }
108
113
 
109
114
  public pointerMove(data?: IPointerEvent): void {
@@ -121,10 +126,11 @@ export class InteractionBase implements IInteraction {
121
126
  }
122
127
 
123
128
  public pointerMoveReal(data: IPointerEvent): void {
129
+ const { dragHover, dragDistance } = this.config.pointer
124
130
  this.emit(PointerEvent.BEFORE_MOVE, data, this.defaultPath)
125
131
 
126
132
  if (this.downData) {
127
- const canDrag = PointHelper.getDistance(this.downData, data) > this.config.pointer.dragDistance
133
+ const canDrag = PointHelper.getDistance(this.downData, data) > dragDistance
128
134
  if (canDrag) {
129
135
  if (this.waitTap) this.pointerWaitCancel()
130
136
  this.waitMenuTap = false
@@ -139,7 +145,7 @@ export class InteractionBase implements IInteraction {
139
145
 
140
146
  this.emit(PointerEvent.MOVE, data)
141
147
 
142
- if (!(this.dragging && !this.config.pointer.dragHover)) this.pointerHover(data)
148
+ if (!(this.dragging && !dragHover)) this.pointerHover(data)
143
149
 
144
150
  if (this.dragger.dragging) {
145
151
  this.dragger.dragOverOrOut(data)
@@ -156,27 +162,34 @@ export class InteractionBase implements IInteraction {
156
162
  if (!downData) return
157
163
 
158
164
  PointerButton.defaultLeft(data)
159
- this.downData = null // must before pointer.up event
160
165
 
161
166
  this.findPath(data)
167
+ const upData = { ...data, path: data.path.clone() }
168
+
162
169
  data.path.addList(downData.path.list) // downPath必须触发
170
+
163
171
  this.checkPath(data)
164
172
 
173
+ this.downData = null // must before pointer.up event
165
174
  this.emit(PointerEvent.BEFORE_UP, data)
166
175
  this.emit(PointerEvent.UP, data)
167
176
 
168
177
  this.touchLeave(data)
169
178
 
170
- this.tap(data)
171
- this.menuTap(data)
179
+ if (!data.isCancel) {
180
+ this.tap(data)
181
+ this.menuTap(data)
182
+ }
172
183
 
173
184
  this.dragger.dragEnd(data)
174
185
 
175
- this.updateCursor(data)
186
+ this.updateCursor(upData)
176
187
  }
177
188
 
178
189
  public pointerCancel(): void {
179
- this.pointerUp(this.dragger.dragData)
190
+ const data = { ...this.dragger.dragData }
191
+ data.isCancel = true
192
+ this.pointerUp(data)
180
193
  }
181
194
 
182
195
 
@@ -246,8 +259,10 @@ export class InteractionBase implements IInteraction {
246
259
 
247
260
  // helper
248
261
  protected pointerHover(data: IPointerEvent): void {
249
- this.pointerOverOrOut(data)
250
- this.pointerEnterOrLeave(data)
262
+ if (this.config.pointer.hover) {
263
+ this.pointerOverOrOut(data)
264
+ this.pointerEnterOrLeave(data)
265
+ }
251
266
  }
252
267
 
253
268
  protected pointerOverOrOut(data: IPointerEvent): void {
@@ -341,6 +356,12 @@ export class InteractionBase implements IInteraction {
341
356
  return data && (data.path.list[0] as ILeaf).isLeafer
342
357
  }
343
358
 
359
+ public isTreePath(data: IPointerEvent): boolean {
360
+ const app = this.target.app as IApp
361
+ if (!app || !app.isApp) return false
362
+ return app.editor && (!data.path.has(app.editor) && data.path.has(app.tree)) // 当dragEmpty为true时,在手机端(pointer.hover为false)可以拖动tree层(编辑器选中的元素除外)
363
+ }
364
+
344
365
  protected checkPath(data: IPointerEvent, useDefaultPath?: boolean): void {
345
366
  if (useDefaultPath || this.canMove(data)) data.path = this.defaultPath
346
367
  }
@@ -393,7 +414,7 @@ export class InteractionBase implements IInteraction {
393
414
  }
394
415
 
395
416
  public updateCursor(data?: IPointerEvent): void {
396
- if (this.config.cursor.stop) return
417
+ if (this.config.cursor.stop || !this.config.pointer.hover) return
397
418
 
398
419
  if (!data) {
399
420
  this.updateHoverData()
package/src/config.ts CHANGED
@@ -13,6 +13,7 @@ export const config: IInteractionConfig = {
13
13
  tapTime: 120,
14
14
  longPressTime: 800,
15
15
  transformTime: 500,
16
+ hover: true,
16
17
  dragHover: true,
17
18
  dragDistance: 2,
18
19
  swipeDistance: 20,
package/src/index.ts CHANGED
@@ -2,4 +2,28 @@ export { InteractionBase } from './Interaction'
2
2
  export { InteractionHelper } from './InteractionHelper'
3
3
  export { MultiTouchHelper } from './MultiTouchHelper'
4
4
  export { Cursor } from './Cursor'
5
- export { HitCanvasManager } from './HitCanvasManager'
5
+ export { HitCanvasManager } from './HitCanvasManager'
6
+
7
+ import { IPointData, IRadiusPointData, IWindingRule } from '@leafer/interface'
8
+ import { LeaferCanvasBase, tempBounds } from '@leafer/core'
9
+
10
+
11
+ const canvas = LeaferCanvasBase.prototype
12
+
13
+ canvas.hitFill = function (point: IPointData, fillRule?: IWindingRule): boolean {
14
+ return fillRule ? this.context.isPointInPath(point.x, point.y, fillRule) : this.context.isPointInPath(point.x, point.y)
15
+ }
16
+
17
+ canvas.hitStroke = function (point: IPointData, strokeWidth?: number): boolean {
18
+ this.strokeWidth = strokeWidth
19
+ return this.context.isPointInStroke(point.x, point.y)
20
+ }
21
+
22
+ canvas.hitPixel = function (radiusPoint: IRadiusPointData, offset?: IPointData, scale = 1): boolean { // 画布必须有alpha通道
23
+ let { x, y, radiusX, radiusY } = radiusPoint
24
+ if (offset) x -= offset.x, y -= offset.y
25
+ tempBounds.set(x - radiusX, y - radiusY, radiusX * 2, radiusY * 2).scale(scale).ceil()
26
+ const { data } = this.context.getImageData(tempBounds.x, tempBounds.y, tempBounds.width, tempBounds.height)
27
+ for (let i = 0, len = data.length; i < len; i += 4) { if (data[i + 3] > 0) return true }
28
+ return data[3] > 0
29
+ }
package/types/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { IMoveEvent, IZoomEvent, IRotateEvent, ITimer, IDragEvent, IPointerEvent, ILeafList, IFunction, IInteraction, ILeaf, IInteractionCanvas, ISelector, IInteractionConfig, ICursorType, IBounds, IEventListenerId, IBooleanMap, IUIEvent, IKeepTouchData, IKeyEvent, IPickOptions, IPointData, IEvent, IObject, IDropEvent, ISwipeEvent, IMultiTouchData, ICursorTypeMap, IHitCanvasManager, IScreenSizeData, IHitCanvas } from '@leafer/interface';
1
+ import { IMoveEvent, IZoomEvent, IRotateEvent, ITimer, IDragEvent, IPointerEvent, ILeafList, IFunction, IInteraction, ILeaf, IInteractionCanvas, ISelector, IInteractionConfig, ICursorType, IBounds, IEventListenerId, IBooleanMap, IUIEvent, IKeepTouchData, IKeyEvent, IPickOptions, IPointData, IEvent, IObject, IDropEvent, ISwipeEvent, IMultiTouchData, ICursorTypeMap, IHitCanvasManager, ILeaferCanvasConfig, IHitCanvas } from '@leafer/interface';
2
2
  import { LeafList, CanvasManager } from '@leafer/core';
3
3
 
4
4
  declare class Transformer {
@@ -45,8 +45,8 @@ declare class Dragger {
45
45
  dragEnd(data: IPointerEvent, speed?: number): void;
46
46
  protected dragEndReal(data?: IPointerEvent): void;
47
47
  protected animate(func?: IFunction, off?: 'off'): void;
48
- protected swipe(data: IPointerEvent, endDragData: IDragEvent): void;
49
- protected drop(data: IPointerEvent): void;
48
+ protected swipe(data: IPointerEvent, downData: IPointerEvent, dragData: IDragEvent, endDragData: IDragEvent): void;
49
+ protected drop(data: IPointerEvent, dropList: ILeafList, dragEnterPath: ILeafList): void;
50
50
  protected dragReset(): void;
51
51
  checkDragOut(data: IPointerEvent): void;
52
52
  protected autoMoveOnDragOut(data: IPointerEvent): void;
@@ -60,9 +60,12 @@ declare class InteractionBase implements IInteraction {
60
60
  selector: ISelector;
61
61
  running: boolean;
62
62
  get dragging(): boolean;
63
+ get moveMode(): boolean;
63
64
  get isDragEmpty(): boolean;
65
+ get isMobileDragEmpty(): boolean;
66
+ get isHoldMiddleKey(): boolean;
64
67
  get isHoldRightKey(): boolean;
65
- get moveMode(): boolean;
68
+ get isHoldSpaceKey(): boolean;
66
69
  config: IInteractionConfig;
67
70
  cursor: ICursorType | ICursorType[];
68
71
  get hitRadius(): number;
@@ -109,6 +112,7 @@ declare class InteractionBase implements IInteraction {
109
112
  protected tap(data: IPointerEvent): void;
110
113
  findPath(data: IPointerEvent, options?: IPickOptions): ILeafList;
111
114
  isRootPath(data: IPointerEvent): boolean;
115
+ isTreePath(data: IPointerEvent): boolean;
112
116
  protected checkPath(data: IPointerEvent, useDefaultPath?: boolean): void;
113
117
  canMove(data: IPointerEvent): boolean;
114
118
  isDrag(leaf: ILeaf): boolean;
@@ -159,13 +163,15 @@ declare class Cursor {
159
163
  }
160
164
 
161
165
  declare class HitCanvasManager extends CanvasManager implements IHitCanvasManager {
162
- protected pathTypeList: ILeafList;
163
- protected imageTypeList: ILeafList;
164
- getImageType(leaf: ILeaf, size: IScreenSizeData): IHitCanvas;
166
+ maxTotal: number;
167
+ protected pathList: ILeafList;
168
+ protected pixelList: ILeafList;
169
+ getPixelType(leaf: ILeaf, config: ILeaferCanvasConfig): IHitCanvas;
165
170
  getPathType(leaf: ILeaf): IHitCanvas;
166
171
  clearImageType(): void;
167
172
  clearPathType(): void;
168
173
  protected __clearLeafList(leafList: ILeafList): void;
174
+ protected __autoClear(): void;
169
175
  clear(): void;
170
176
  }
171
177