@leafer-in/editor 1.6.7 → 1.7.0

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-in/editor",
3
- "version": "1.6.7",
3
+ "version": "1.7.0",
4
4
  "description": "@leafer-in/editor",
5
5
  "author": "Chao (Leafer) Wan",
6
6
  "license": "MIT",
@@ -34,10 +34,10 @@
34
34
  "leaferjs"
35
35
  ],
36
36
  "peerDependencies": {
37
- "@leafer-ui/draw": "^1.6.7",
38
- "@leafer-ui/core": "^1.6.7",
39
- "@leafer-in/resize": "^1.6.7",
40
- "@leafer-ui/interface": "^1.6.7",
41
- "@leafer-in/interface": "^1.6.7"
37
+ "@leafer-ui/draw": "^1.7.0",
38
+ "@leafer-ui/core": "^1.7.0",
39
+ "@leafer-in/resize": "^1.7.0",
40
+ "@leafer-ui/interface": "^1.7.0",
41
+ "@leafer-in/interface": "^1.7.0"
42
42
  }
43
43
  }
package/src/Editor.ts CHANGED
@@ -1,13 +1,8 @@
1
1
  import { IGroupInputData, IUI, IEventListenerId, IPointData, ILeafList, IEditSize, IGroup, IObject, IAlign, IAxis, IFunction, IMatrix, IApp } from '@leafer-ui/interface'
2
- import { Group, DataHelper, MathHelper, LeafList, Matrix, RenderEvent, LeafHelper, Direction9, Plugin } from '@leafer-ui/draw'
3
- import { DragEvent, RotateEvent, KeyEvent, ZoomEvent, MoveEvent } from '@leafer-ui/core'
2
+ import { Group, DataHelper, LeafList, RenderEvent, LeafHelper, Direction9, Plugin } from '@leafer-ui/draw'
3
+ import { DragEvent, RotateEvent, ZoomEvent, MoveEvent, useModule } from '@leafer-ui/core'
4
4
 
5
- import { IEditBox, IEditPoint, IEditor, IEditorConfig, IEditTool, IEditorScaleEvent, IInnerEditor, ISimulateElement, IEditorMoveEvent, IEditorRotateEvent, IEditorSkewEvent } from '@leafer-in/interface'
6
-
7
- import { EditorMoveEvent } from './event/EditorMoveEvent'
8
- import { EditorScaleEvent } from './event/EditorScaleEvent'
9
- import { EditorRotateEvent } from './event/EditorRotateEvent'
10
- import { EditorSkewEvent } from './event/EditorSkewEvent'
5
+ import { IEditBox, IEditPoint, IEditor, IEditorConfig, IEditTool, IEditorScaleEvent, IInnerEditor, ISimulateElement } from '@leafer-in/interface'
11
6
 
12
7
  import { EditSelect } from './display/EditSelect'
13
8
  import { EditBox } from './display/EditBox'
@@ -18,15 +13,14 @@ import { config } from './config'
18
13
  import { onTarget, onHover } from './editor/target'
19
14
  import { targetAttr, mergeConfigAttr } from './decorator/data'
20
15
  import { EditorHelper } from './helper/EditorHelper'
21
- import { EditDataHelper } from './helper/EditDataHelper'
22
16
  import { simulate } from './editor/simulate'
23
- import { updateCursor } from './editor/cursor'
24
17
  import { EditToolCreator } from './tool/EditToolCreator'
25
18
  import { InnerEditorEvent } from './event/InnerEditorEvent'
26
19
  import { EditorGroupEvent } from './event/EditorGroupEvent'
27
20
  import { SimulateElement } from './display/SimulateElement'
21
+ import { TransformTool } from './tool/TransformTool'
28
22
 
29
-
23
+ @useModule(TransformTool, ['editBox', 'editTool', 'emitEvent'])
30
24
  export class Editor extends Group implements IEditor {
31
25
 
32
26
  public config: IEditorConfig
@@ -137,7 +131,7 @@ export class Editor extends Group implements IEditor {
137
131
  }
138
132
 
139
133
  public updateEditTool(): void {
140
- const tool = this.editTool
134
+ let tool = this.editTool
141
135
  if (tool) {
142
136
  this.editBox.unload()
143
137
  tool.unload()
@@ -145,10 +139,11 @@ export class Editor extends Group implements IEditor {
145
139
  }
146
140
 
147
141
  if (this.editing) {
148
- const tag = this.single ? this.list[0].editOuter as string : 'EditTool'
149
- this.editTool = this.editToolList[tag] = this.editToolList[tag] || EditToolCreator.get(tag, this)
142
+ const tag = this.element.editOuter || 'EditTool'
143
+ tool = this.editTool = this.editToolList[tag] = this.editToolList[tag] || EditToolCreator.get(tag, this)
150
144
  this.editBox.load()
151
- this.editTool.load()
145
+ tool.load()
146
+ this.update()
152
147
  }
153
148
  }
154
149
 
@@ -159,232 +154,41 @@ export class Editor extends Group implements IEditor {
159
154
  return this.mergeConfig.editSize
160
155
  }
161
156
 
162
- // operate
163
-
164
- public onMove(e: DragEvent | MoveEvent): void {
165
- if (e instanceof MoveEvent) {
166
-
167
- if (e.moveType !== 'drag') {
168
- const { moveable, resizeable } = this.mergeConfig
169
- const move = e.getLocalMove(this.element)
170
- if (moveable === 'move') e.stop(), this.move(move.x, move.y)
171
- else if (resizeable === 'zoom') e.stop()
172
- }
173
-
174
- } else {
175
-
176
- const total = { x: e.totalX, y: e.totalY }
177
-
178
- if (e.shiftKey) {
179
- if (Math.abs(total.x) > Math.abs(total.y)) total.y = 0
180
- else total.x = 0
181
- }
182
-
183
- this.move(DragEvent.getValidMove(this.element, this.editBox.dragStartData.point, total))
184
-
185
- }
186
- }
187
-
188
- public onScale(e: DragEvent | ZoomEvent): void {
189
- const { element } = this
190
- let { around, lockRatio, resizeable, flipable, editSize } = this.mergeConfig
191
157
 
192
- if (e instanceof ZoomEvent) {
158
+ // TransformTool will rewrite -----
193
159
 
194
- if (resizeable === 'zoom') e.stop(), this.scaleOf(element.getBoxPoint(e), e.scale, e.scale)
160
+ // operate
195
161
 
196
- } else {
162
+ public onMove(_e: DragEvent | MoveEvent): void { }
197
163
 
198
- const { direction } = e.current as IEditPoint
164
+ public onScale(_e: DragEvent | ZoomEvent): void { }
199
165
 
200
- if (e.shiftKey || element.lockRatio) lockRatio = true
166
+ public onRotate(_e: DragEvent | RotateEvent): void { }
201
167
 
202
- const data = EditDataHelper.getScaleData(element, this.editBox.dragStartData.bounds, direction, e.getInnerTotal(element), lockRatio, EditDataHelper.getAround(around, e.altKey), flipable, this.multiple || editSize === 'scale')
203
-
204
- if (this.editTool.onScaleWithDrag) {
205
- data.drag = e
206
- this.scaleWithDrag(data)
207
- } else {
208
- this.scaleOf(data.origin, data.scaleX, data.scaleY)
209
- }
210
-
211
- }
212
- }
213
-
214
- public onRotate(e: DragEvent | RotateEvent): void {
215
- const { skewable, rotateable, around, rotateGap } = this.mergeConfig
216
- const { direction, name } = e.current as IEditPoint
217
- if (skewable && name === 'resize-line') return this.onSkew(e as DragEvent)
218
-
219
- const { element } = this, { dragStartData } = this.editBox
220
- let origin: IPointData, rotation: number
221
-
222
- if (e instanceof RotateEvent) {
223
-
224
- if (rotateable === 'rotate') e.stop(), rotation = e.rotation, origin = element.getBoxPoint(e)
225
- else return
226
-
227
- if (element.scaleX * element.scaleY < 0) rotation = -rotation // flippedOne
228
-
229
- } else {
230
-
231
- const data = EditDataHelper.getRotateData(element.boxBounds, direction, e.getBoxPoint(element), element.getBoxPoint(dragStartData), e.shiftKey ? null : (element.around || element.origin || around || 'center'))
232
- rotation = data.rotation
233
- origin = data.origin
234
-
235
- }
236
-
237
- if (element.scaleX * element.scaleY < 0) rotation = -rotation // flippedOne
238
- if (e instanceof DragEvent) rotation = dragStartData.rotation + rotation - element.rotation
239
-
240
- rotation = MathHelper.float(MathHelper.getGapRotation(rotation, rotateGap, element.rotation), 2)
241
- if (!rotation) return
242
-
243
- this.rotateOf(origin, rotation)
244
- }
245
-
246
-
247
- public onSkew(e: DragEvent): void {
248
- const { element } = this
249
- const { around } = this.mergeConfig
250
-
251
- const { origin, skewX, skewY } = EditDataHelper.getSkewData(element.boxBounds, (e.current as IEditPoint).direction, e.getInnerMove(element), EditDataHelper.getAround(around, e.altKey))
252
- if (!skewX && !skewY) return
253
-
254
- this.skewOf(origin, skewX, skewY)
255
- }
168
+ public onSkew(_e: DragEvent): void { }
256
169
 
257
170
 
258
171
  // transform
259
172
 
260
- public move(x: number | IPointData, y = 0): void {
261
- if (!this.checkTransform('moveable')) return
262
- if (typeof x === 'object') y = x.y, x = x.x
173
+ public move(_x: number | IPointData, _y = 0): void { }
263
174
 
264
- const { element: target } = this, { beforeMove } = this.mergeConfig
265
- if (beforeMove) {
266
- const check = beforeMove({ target, x, y })
267
- if (typeof check === 'object') x = check.x, y = check.y
268
- else if (check === false) return
269
- }
175
+ public scaleWithDrag(_data: IEditorScaleEvent): void { }
270
176
 
271
- const world = target.getWorldPointByLocal({ x, y }, null, true)
272
- if (this.multiple) target.safeChange(() => target.move(x, y))
273
- const data: IEditorMoveEvent = { target, editor: this, moveX: world.x, moveY: world.y }
177
+ override scaleOf(_origin: IPointData | IAlign, scaleX: number, _scaleY = scaleX, _resize?: boolean): void { }
274
178
 
275
- this.emitEvent(new EditorMoveEvent(EditorMoveEvent.BEFORE_MOVE, data))
276
- const event = new EditorMoveEvent(EditorMoveEvent.MOVE, data)
277
- this.editTool.onMove(event)
278
- this.emitEvent(event)
279
- }
280
-
281
- public scaleWithDrag(data: IEditorScaleEvent): void {
282
- if (!this.checkTransform('resizeable')) return
283
-
284
- const { element: target } = this, { beforeScale } = this.mergeConfig
285
- if (beforeScale) {
286
- const { origin, scaleX, scaleY, drag } = data
287
- const check = beforeScale({ target, drag, origin, scaleX, scaleY })
288
- if (check === false) return
289
- }
290
-
291
- data = { ...data, target, editor: this, worldOrigin: target.getWorldPoint(data.origin) }
292
-
293
- this.emitEvent(new EditorScaleEvent(EditorScaleEvent.BEFORE_SCALE, data))
294
- const event = new EditorScaleEvent(EditorScaleEvent.SCALE, data)
295
- this.editTool.onScaleWithDrag(event)
296
- this.emitEvent(event)
297
- }
298
-
299
-
300
- override scaleOf(origin: IPointData | IAlign, scaleX: number, scaleY = scaleX, _resize?: boolean): void {
301
- if (!this.checkTransform('resizeable')) return
302
-
303
- const { element: target } = this, { beforeScale } = this.mergeConfig
304
- if (beforeScale) {
305
- const check = beforeScale({ target, origin, scaleX, scaleY })
306
- if (typeof check === 'object') scaleX = check.scaleX, scaleY = check.scaleY
307
- else if (check === false) return
308
- }
309
-
310
- const worldOrigin = this.getWorldOrigin(origin)
311
- const transform = this.multiple && this.getChangedTransform(() => target.safeChange(() => target.scaleOf(origin, scaleX, scaleY)))
312
- const data: IEditorScaleEvent = { target, editor: this, worldOrigin, scaleX, scaleY, transform }
313
-
314
- this.emitEvent(new EditorScaleEvent(EditorScaleEvent.BEFORE_SCALE, data))
315
- const event = new EditorScaleEvent(EditorScaleEvent.SCALE, data)
316
- this.editTool.onScale(event)
317
- this.emitEvent(event)
318
- }
319
-
320
- override flip(axis: IAxis): void {
321
- if (!this.checkTransform('resizeable')) return
322
-
323
- const { element } = this
324
- const worldOrigin = this.getWorldOrigin('center')
325
- const transform = this.multiple ? this.getChangedTransform(() => element.safeChange(() => element.flip(axis))) : new Matrix(LeafHelper.getFlipTransform(element, axis))
326
- const data: IEditorScaleEvent = { target: element, editor: this, worldOrigin, scaleX: axis === 'x' ? -1 : 1, scaleY: axis === 'y' ? -1 : 1, transform }
179
+ override flip(_axis: IAxis): void { }
327
180
 
328
- this.emitEvent(new EditorScaleEvent(EditorScaleEvent.BEFORE_SCALE, data))
329
- const event = new EditorScaleEvent(EditorScaleEvent.SCALE, data)
330
- this.editTool.onScale(event)
331
- this.emitEvent(event)
332
- }
333
-
334
- override rotateOf(origin: IPointData | IAlign, rotation: number): void {
335
- if (!this.checkTransform('rotateable')) return
336
-
337
- const { element: target } = this, { beforeRotate } = this.mergeConfig
338
- if (beforeRotate) {
339
- const check = beforeRotate({ target, origin, rotation })
340
- if (typeof check === 'number') rotation = check
341
- else if (check === false) return
342
- }
181
+ override rotateOf(_origin: IPointData | IAlign, _rotation: number): void { }
343
182
 
344
- const worldOrigin = this.getWorldOrigin(origin)
345
- const transform = this.multiple && this.getChangedTransform(() => target.safeChange(() => target.rotateOf(origin, rotation)))
346
- const data: IEditorRotateEvent = { target, editor: this, worldOrigin, rotation, transform }
183
+ override skewOf(_origin: IPointData | IAlign, _skewX: number, _skewY = 0, _resize?: boolean): void { }
347
184
 
348
- this.emitEvent(new EditorRotateEvent(EditorRotateEvent.BEFORE_ROTATE, data))
349
- const event = new EditorRotateEvent(EditorRotateEvent.ROTATE, data)
350
- this.editTool.onRotate(event)
351
- this.emitEvent(event)
352
- }
185
+ public checkTransform(_type: 'moveable' | 'resizeable' | 'rotateable' | 'skewable'): boolean { return undefined }
353
186
 
354
- override skewOf(origin: IPointData | IAlign, skewX: number, skewY = 0, _resize?: boolean): void {
355
- if (!this.checkTransform('skewable')) return
187
+ protected getWorldOrigin(_origin: IPointData | IAlign): IPointData { return undefined }
356
188
 
357
- const { element: target } = this, { beforeSkew } = this.mergeConfig
358
- if (beforeSkew) {
359
- const check = beforeSkew({ target, origin, skewX, skewY })
360
- if (typeof check === 'object') skewX = check.skewX, skewY = check.skewY
361
- else if (check === false) return
362
- }
189
+ protected getChangedTransform(_func: IFunction): IMatrix { return undefined }
363
190
 
364
- const worldOrigin = this.getWorldOrigin(origin)
365
- const transform = this.multiple && this.getChangedTransform(() => target.safeChange(() => target.skewOf(origin, skewX, skewY)))
366
- const data: IEditorSkewEvent = { target, editor: this, worldOrigin, skewX, skewY, transform }
367
-
368
- this.emitEvent(new EditorSkewEvent(EditorSkewEvent.BEFORE_SKEW, data))
369
- const event = new EditorSkewEvent(EditorSkewEvent.SKEW, data)
370
- this.editTool.onSkew(event)
371
- this.emitEvent(event)
372
- }
373
-
374
- public checkTransform(type: 'moveable' | 'resizeable' | 'rotateable' | 'skewable'): boolean { return this.element && !this.element.locked && this.mergeConfig[type] as boolean }
375
-
376
- protected getWorldOrigin(origin: IPointData | IAlign): IPointData {
377
- return this.element.getWorldPoint(LeafHelper.getInnerOrigin(this.element, origin))
378
- }
379
-
380
- protected getChangedTransform(func: IFunction): IMatrix {
381
- const { element } = this
382
- if (this.multiple && !element.canChange) return element.changedTransform
383
-
384
- const oldMatrix = new Matrix(element.worldTransform)
385
- func()
386
- return new Matrix(element.worldTransform).divide(oldMatrix) // world change transform
387
- }
191
+ // --------
388
192
 
389
193
 
390
194
  // group
@@ -525,15 +329,12 @@ export class Editor extends Group implements IEditor {
525
329
  if (this.targetChanged) this.update()
526
330
  }
527
331
 
528
- protected onKey(e: KeyEvent): void {
529
- updateCursor(this, e)
530
- }
531
332
 
532
333
  // event
533
334
 
534
335
  public listenTargetEvents(): void {
535
336
  if (!this.targetEventIds.length) {
536
- const { app, leafer, editBox, editMask } = this
337
+ const { app, leafer, editMask } = this
537
338
  this.targetEventIds = [
538
339
  leafer.on_(RenderEvent.START, this.onRenderStart, this),
539
340
 
@@ -543,9 +344,6 @@ export class Editor extends Group implements IEditor {
543
344
  [MoveEvent.BEFORE_MOVE, this.onMove, this, true],
544
345
  [ZoomEvent.BEFORE_ZOOM, this.onScale, this, true],
545
346
  [RotateEvent.BEFORE_ROTATE, this.onRotate, this, true],
546
-
547
- [[KeyEvent.HOLD, KeyEvent.UP], this.onKey, this],
548
- [KeyEvent.DOWN, editBox.onArrow, editBox]
549
347
  ])
550
348
  ]
551
349
  if (editMask.visible) editMask.forceRender()
@@ -1,6 +1,6 @@
1
- import { IRect, IEventListenerId, IBoundsData, IPointData, IKeyEvent, IGroup, IBox, IBoxInputData, IAlign, IUI, IEditorConfig, IEditorDragStartData, IEventParams } from '@leafer-ui/interface'
1
+ import { IRect, IEventListenerId, IBoundsData, IPointData, IKeyEvent, IGroup, IBox, IBoxInputData, IAlign, IUI, IEditorConfig, IEditorDragStartData, IEventParams, ITransformTool } from '@leafer-ui/interface'
2
2
  import { Group, Box, Text, AroundHelper, Direction9, ResizeEvent } from '@leafer-ui/draw'
3
- import { DragEvent, PointerEvent } from '@leafer-ui/core'
3
+ import { DragEvent, PointerEvent, KeyEvent } from '@leafer-ui/core'
4
4
 
5
5
  import { IEditBox, IEditor, IEditPoint, IEditPointType } from '@leafer-in/interface'
6
6
 
@@ -15,6 +15,7 @@ const fourDirection = ['top', 'right', 'bottom', 'left'], editConfig: IEditorCon
15
15
  export class EditBox extends Group implements IEditBox {
16
16
 
17
17
  public editor: IEditor
18
+
18
19
  public dragging: boolean
19
20
  public moving: boolean
20
21
 
@@ -33,6 +34,24 @@ export class EditBox extends Group implements IEditBox {
33
34
 
34
35
  public dragStartData = {} as IEditorDragStartData
35
36
 
37
+ public config: IEditorConfig
38
+ public mergedConfig: IEditorConfig
39
+
40
+ public get mergeConfig(): IEditorConfig {
41
+ const { config } = this, { mergeConfig } = this.editor
42
+ return this.mergedConfig = config ? { ...mergeConfig, ...config } : mergeConfig
43
+ }
44
+
45
+ protected _target: IUI
46
+ public get target(): IUI { return this._target || this.editor.element } // 操作的元素,默认为editor.element
47
+ public set target(target: IUI) { this._target = target }
48
+
49
+ public get single(): boolean { return !!this._target || this.editor.single }
50
+
51
+ protected _transformTool: ITransformTool
52
+ public get transformTool(): ITransformTool { return this._transformTool || this.editor }
53
+ public set transformTool(tool: ITransformTool) { this._transformTool = tool }
54
+
36
55
  // fliped
37
56
  public get flipped(): boolean { return this.flippedX || this.flippedY }
38
57
  public get flippedX(): boolean { return this.scaleX < 0 }
@@ -77,8 +96,7 @@ export class EditBox extends Group implements IEditBox {
77
96
  }
78
97
 
79
98
  public load(): void {
80
- const { mergeConfig, element, single } = this.editor
81
- const { rect, circle, resizePoints } = this
99
+ const { target, mergeConfig, single, rect, circle, resizePoints } = this
82
100
  const { stroke, strokeWidth } = mergeConfig
83
101
 
84
102
  const pointsStyle = this.getPointsStyle()
@@ -97,22 +115,34 @@ export class EditBox extends Group implements IEditBox {
97
115
 
98
116
  // rect
99
117
  rect.set({ stroke, strokeWidth, editConfig, ...(mergeConfig.rect || {}) })
100
- rect.hittable = !single
101
- rect.syncEventer = single && this.editor // 单选下 rect 的事件不会冒泡,需要手动传递给editor
118
+
119
+ const syncEventer = single && this.transformTool.editTool
120
+
121
+ rect.hittable = !syncEventer
122
+ rect.syncEventer = syncEventer && this.editor // 单选下 rect 的事件不会冒泡,需要手动传递给editor
102
123
 
103
124
  // 编辑框作为底部虚拟元素, 在 onSelect 方法移除
104
- if (single) {
105
- element.syncEventer = rect
106
- this.app.interaction.bottomList = [{ target: rect, proxy: element }]
125
+ if (syncEventer) {
126
+ target.syncEventer = rect
127
+ this.app.interaction.bottomList = [{ target: rect, proxy: target }]
107
128
  }
129
+
130
+ updateMoveCursor(this)
108
131
  }
109
132
 
110
- public update(bounds: IBoundsData): void {
111
- const { rect, circle, buttons, resizePoints, rotatePoints, resizeLines, editor } = this
112
- const { mergeConfig, element, multiple, editMask } = editor
133
+ public update(): void {
134
+ const { editor } = this
135
+ const { x, y, scaleX, scaleY, rotation, skewX, skewY, width, height } = this.target.getLayoutBounds('box', editor, true)
136
+ this.set({ x, y, scaleX, scaleY, rotation, skewX, skewY })
137
+ this.updateBounds({ x: 0, y: 0, width, height })
138
+ }
139
+
140
+ public updateBounds(bounds: IBoundsData): void {
141
+ const { editMask } = this.editor
142
+ const { mergeConfig, single, rect, circle, buttons, resizePoints, rotatePoints, resizeLines } = this
113
143
  const { middlePoint, resizeable, rotateable, hideOnSmall, editBox, mask } = mergeConfig
114
144
 
115
- this.visible = !element.locked
145
+ this.visible = !this.target.locked
116
146
  editMask.visible = mask ? true : 0
117
147
 
118
148
  if (this.view.worldOpacity) {
@@ -154,27 +184,27 @@ export class EditBox extends Group implements IEditBox {
154
184
 
155
185
  // rotate
156
186
  circle.visible = showPoints && rotateable && !!(mergeConfig.circle || mergeConfig.rotatePoint)
157
- if (circle.visible) this.layoutCircle(mergeConfig)
187
+ if (circle.visible) this.layoutCircle()
158
188
 
159
189
  // rect
160
190
  if (rect.path) rect.path = null // line可能会变成path优先模式
161
- rect.set({ ...bounds, visible: multiple ? true : editBox })
191
+ rect.set({ ...bounds, visible: single ? editBox : true })
162
192
 
163
193
  // buttons
164
194
  buttons.visible = showPoints && buttons.children.length > 0 || 0
165
- if (buttons.visible) this.layoutButtons(mergeConfig)
195
+ if (buttons.visible) this.layoutButtons()
166
196
  } else rect.set(bounds) // 需要更新大小
167
197
  }
168
198
 
169
- protected layoutCircle(config: IEditorConfig): void {
170
- const { circleDirection, circleMargin, buttonsMargin, buttonsDirection, middlePoint } = config
199
+ protected layoutCircle(): void {
200
+ const { circleDirection, circleMargin, buttonsMargin, buttonsDirection, middlePoint } = this.mergedConfig
171
201
  const direction = fourDirection.indexOf(circleDirection || ((this.buttons.children.length && buttonsDirection === 'bottom') ? 'top' : 'bottom'))
172
202
  this.setButtonPosition(this.circle, direction, circleMargin || buttonsMargin, !!middlePoint)
173
203
  }
174
204
 
175
- protected layoutButtons(config: IEditorConfig): void {
205
+ protected layoutButtons(): void {
176
206
  const { buttons } = this
177
- const { buttonsDirection, buttonsFixed, buttonsMargin, middlePoint } = config
207
+ const { buttonsDirection, buttonsFixed, buttonsMargin, middlePoint } = this.mergedConfig
178
208
 
179
209
  const { flippedX, flippedY } = this
180
210
  let index = fourDirection.indexOf(buttonsDirection)
@@ -214,18 +244,18 @@ export class EditBox extends Group implements IEditBox {
214
244
 
215
245
 
216
246
  public getPointStyle(userStyle?: IBoxInputData): IBoxInputData {
217
- const { stroke, strokeWidth, pointFill, pointSize, pointRadius } = this.editor.mergeConfig
247
+ const { stroke, strokeWidth, pointFill, pointSize, pointRadius } = this.mergedConfig
218
248
  const defaultStyle = { fill: pointFill, stroke, strokeWidth, around: 'center', strokeAlign: 'center', width: pointSize, height: pointSize, cornerRadius: pointRadius, offsetX: 0, offsetY: 0, editConfig } as IBoxInputData
219
249
  return userStyle ? Object.assign(defaultStyle, userStyle) : defaultStyle
220
250
  }
221
251
 
222
252
  public getPointsStyle(): IBoxInputData[] {
223
- const { point } = this.editor.mergeConfig
253
+ const { point } = this.mergedConfig
224
254
  return point instanceof Array ? point : [point]
225
255
  }
226
256
 
227
257
  public getMiddlePointsStyle(): IBoxInputData[] {
228
- const { middlePoint } = this.editor.mergeConfig
258
+ const { middlePoint } = this.mergedConfig
229
259
  return middlePoint instanceof Array ? middlePoint : (middlePoint ? [middlePoint] : this.getPointsStyle())
230
260
  }
231
261
 
@@ -241,16 +271,16 @@ export class EditBox extends Group implements IEditBox {
241
271
  protected onDragStart(e: DragEvent): void {
242
272
  this.dragging = true
243
273
  const point = this.dragPoint = e.current as IEditPoint, { pointType } = point
244
- const { editor, dragStartData } = this, { element } = editor
274
+ const { editor, dragStartData } = this, { target } = this
245
275
  if (point.name === 'rect') {
246
276
  this.moving = true
247
- editor.opacity = editor.mergeConfig.hideOnMove ? 0 : 1 // move
277
+ editor.opacity = this.mergeConfig.hideOnMove ? 0 : 1 // move
248
278
  }
249
279
  dragStartData.x = e.x
250
280
  dragStartData.y = e.y
251
- dragStartData.point = { x: element.x, y: element.y } // 用于移动
252
- dragStartData.bounds = { ...element.getLayoutBounds('box', 'local') } // 用于resize
253
- dragStartData.rotation = element.rotation // 用于旋转
281
+ dragStartData.point = { x: target.x, y: target.y } // 用于移动
282
+ dragStartData.bounds = { ...target.getLayoutBounds('box', 'local') } // 用于resize
283
+ dragStartData.rotation = target.rotation // 用于旋转
254
284
  if (pointType && pointType.includes('resize')) ResizeEvent.resizingKeys = editor.leafList.keys // 记录正在resize中的元素列表
255
285
  }
256
286
 
@@ -264,19 +294,28 @@ export class EditBox extends Group implements IEditBox {
264
294
  }
265
295
 
266
296
  protected onDrag(e: DragEvent): void {
267
- const { editor } = this
268
- const { pointType } = this.enterPoint = e.current as IEditPoint
269
- if (pointType.includes('rotate') || e.metaKey || e.ctrlKey || !editor.mergeConfig.resizeable) {
270
- editor.onRotate(e)
271
- if (pointType === 'resize-rotate') editor.onScale(e)
272
- } else if (pointType === 'resize') editor.onScale(e)
273
- if (pointType === 'skew') editor.onSkew(e)
274
- updateCursor(editor, e)
297
+ const { transformTool } = this, point = e.current as IEditPoint
298
+ if (point.name === 'rect') {
299
+ transformTool.onMove(e)
300
+ updateMoveCursor(this)
301
+ } else {
302
+ const { pointType } = this.enterPoint = point
303
+ if (pointType.includes('rotate') || e.metaKey || e.ctrlKey || !this.mergeConfig.resizeable) {
304
+ transformTool.onRotate(e)
305
+ if (pointType === 'resize-rotate') transformTool.onScale(e)
306
+ } else if (pointType === 'resize') transformTool.onScale(e)
307
+ if (pointType === 'skew') transformTool.onSkew(e)
308
+ updateCursor(this, e)
309
+ }
310
+ }
311
+
312
+ protected onKey(e: KeyEvent): void {
313
+ updateCursor(this, e)
275
314
  }
276
315
 
277
316
  public onArrow(e: IKeyEvent): void {
278
317
  const { editor } = this
279
- if (editor.editing && editor.mergeConfig.keyEvent) {
318
+ if (editor.editing && this.mergeConfig.keyEvent) {
280
319
  let x = 0, y = 0
281
320
  const distance = e.shiftKey ? 10 : 1
282
321
  switch (e.code) {
@@ -298,26 +337,27 @@ export class EditBox extends Group implements IEditBox {
298
337
 
299
338
 
300
339
  protected onDoubleTap(e: PointerEvent): void {
301
- if (this.editor.mergeConfig.openInner === 'double') this.openInner(e)
340
+ const { openInner, preventEditInner } = this.mergeConfig
341
+ if (openInner === 'double' && !preventEditInner) this.openInner(e)
302
342
  }
303
343
 
304
344
  protected onLongPress(e: PointerEvent): void {
305
- if (this.editor.mergeConfig.openInner === 'long') this.openInner(e)
345
+ const { openInner, preventEditInner } = this.mergeConfig
346
+ if (openInner === 'long' && preventEditInner) this.openInner(e)
306
347
  }
307
348
 
308
349
  protected openInner(e: PointerEvent): void {
309
- const { editor } = this
310
- if (editor.single) {
311
- const { element } = editor
312
- if (element.locked) return
313
- if (element.isBranch && !element.editInner) {
314
- if ((element as IBox).textBox) {
315
- const { children } = element
350
+ const { editor, target } = this
351
+ if (this.single) {
352
+ if (target.locked) return
353
+ if (target.isBranch && !target.editInner) {
354
+ if ((target as IBox).textBox) {
355
+ const { children } = target
316
356
  const find = children.find(item => item.editable && item instanceof Text) || children.find(item => item instanceof Text)
317
357
  if (find) return editor.openInnerEditor(find) // 文本Box直接进入编辑状态,如便利贴文本
318
358
  }
319
359
 
320
- editor.openGroup(element as IGroup)
360
+ editor.openGroup(target as IGroup)
321
361
  editor.target = editor.selector.findDeepOne(e)
322
362
  } else {
323
363
  editor.openInnerEditor()
@@ -327,7 +367,6 @@ export class EditBox extends Group implements IEditBox {
327
367
 
328
368
 
329
369
  public listenPointEvents(point: IEditPoint, type: IEditPointType, direction: Direction9): void {
330
- const { editor } = this
331
370
  point.direction = direction
332
371
  point.pointType = type
333
372
 
@@ -337,25 +376,35 @@ export class EditBox extends Group implements IEditBox {
337
376
  [DragEvent.END, this.onDragEnd, this],
338
377
  [PointerEvent.LEAVE, () => { this.enterPoint = null }],
339
378
  ]
340
- if (point.name !== 'circle') events.push([PointerEvent.ENTER, (e: PointerEvent) => { this.enterPoint = point, updateCursor(editor, e) }])
379
+ if (point.name !== 'circle') events.push([PointerEvent.ENTER, (e: PointerEvent) => { this.enterPoint = point, updateCursor(this, e) }])
341
380
  this.__eventIds.push(point.on_(events))
342
381
  }
343
382
 
344
383
  protected __listenEvents(): void {
345
- const { rect, editor } = this
346
- this.__eventIds.push(
384
+ const { rect, editor, __eventIds: events } = this
385
+
386
+ events.push(
347
387
  editor.on_(EditorEvent.SELECT, this.onSelect, this),
348
388
 
349
389
  rect.on_([
350
390
  [DragEvent.START, this.onDragStart, this],
351
- [DragEvent.DRAG, editor.onMove, editor],
391
+ [DragEvent.DRAG, this.onDrag, this],
352
392
  [DragEvent.END, this.onDragEnd, this],
353
393
 
354
- [PointerEvent.ENTER, () => updateMoveCursor(editor)],
394
+ [PointerEvent.ENTER, () => updateMoveCursor(this)],
355
395
  [PointerEvent.DOUBLE_TAP, this.onDoubleTap, this],
356
396
  [PointerEvent.LONG_PRESS, this.onLongPress, this]
357
397
  ])
358
398
  )
399
+
400
+ this.waitLeafer(() => {
401
+ events.push(
402
+ editor.app.on_([
403
+ [[KeyEvent.HOLD, KeyEvent.UP], this.onKey, this],
404
+ [KeyEvent.DOWN, this.onArrow, this]
405
+ ])
406
+ )
407
+ })
359
408
  }
360
409
 
361
410
  protected __removeListenEvents(): void {