@leafer-in/editor 1.7.0 → 1.8.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.7.0",
3
+ "version": "1.8.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.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"
37
+ "@leafer-ui/draw": "^1.8.0",
38
+ "@leafer-ui/core": "^1.8.0",
39
+ "@leafer-in/resize": "^1.8.0",
40
+ "@leafer-ui/interface": "^1.8.0",
41
+ "@leafer-in/interface": "^1.8.0"
42
42
  }
43
43
  }
package/src/Editor.ts CHANGED
@@ -52,9 +52,15 @@ export class Editor extends Group implements IEditor {
52
52
  public get multiple(): boolean { return this.list.length > 1 }
53
53
  public get single(): boolean { return this.list.length === 1 }
54
54
 
55
+ public get dragPoint(): IEditPoint { return this.editBox.dragPoint }
56
+
55
57
  public get dragging(): boolean { return this.editBox.dragging }
58
+ public get gesturing(): boolean { return this.editBox.gesturing } // 手势操作元素中
59
+
56
60
  public get moving(): boolean { return this.editBox.moving }
57
- public get dragPoint(): IEditPoint { return this.editBox.dragPoint }
61
+ public get resizing(): boolean { return this.editBox.resizing }
62
+ public get rotating(): boolean { return this.editBox.rotating }
63
+ public get skewing(): boolean { return this.editBox.skewing }
58
64
 
59
65
  // 组件
60
66
 
@@ -131,22 +137,26 @@ export class Editor extends Group implements IEditor {
131
137
  }
132
138
 
133
139
  public updateEditTool(): void {
134
- let tool = this.editTool
135
- if (tool) {
136
- this.editBox.unload()
137
- tool.unload()
138
- this.editTool = null
139
- }
140
+ this.unloadEditTool()
140
141
 
141
142
  if (this.editing) {
142
- const tag = this.element.editOuter || 'EditTool'
143
- tool = this.editTool = this.editToolList[tag] = this.editToolList[tag] || EditToolCreator.get(tag, this)
143
+ const name = this.element.editOuter || 'EditTool'
144
+ const tool = this.editTool = this.editToolList[name] = this.editToolList[name] || EditToolCreator.get(name, this)
144
145
  this.editBox.load()
145
146
  tool.load()
146
147
  this.update()
147
148
  }
148
149
  }
149
150
 
151
+ public unloadEditTool(): void {
152
+ let tool = this.editTool
153
+ if (tool) {
154
+ this.editBox.unload()
155
+ tool.unload()
156
+ this.editTool = null
157
+ }
158
+ }
159
+
150
160
 
151
161
  // get
152
162
 
@@ -255,15 +265,20 @@ export class Editor extends Group implements IEditor {
255
265
 
256
266
  // inner
257
267
 
258
- public openInnerEditor(target?: IUI, select?: boolean): void {
268
+ public openInnerEditor(target?: IUI, nameOrSelect?: string | boolean, select?: boolean): void {
269
+ let name: string
270
+ if (typeof nameOrSelect === 'string') name = nameOrSelect
271
+ else if (!select) select = nameOrSelect
272
+
259
273
  if (target && select) this.target = target
274
+
260
275
  if (this.single) {
261
276
  const editTarget = target || this.element
262
- const tag = editTarget.editInner
263
- if (tag && EditToolCreator.list[tag]) {
277
+ name || (name = editTarget.editInner)
278
+ if (name && EditToolCreator.list[name]) {
264
279
  this.editTool.unload()
265
280
  this.innerEditing = true
266
- this.innerEditor = this.editToolList[tag] || EditToolCreator.get(tag, this)
281
+ this.innerEditor = this.editToolList[name] = this.editToolList[name] || EditToolCreator.get(name, this)
267
282
  this.innerEditor.editTarget = editTarget
268
283
 
269
284
  this.emitInnerEvent(InnerEditorEvent.BEFORE_OPEN)
@@ -273,7 +288,7 @@ export class Editor extends Group implements IEditor {
273
288
  }
274
289
  }
275
290
 
276
- public closeInnerEditor(): void {
291
+ public closeInnerEditor(onlyInnerEditor?: boolean): void {
277
292
  if (this.innerEditing) {
278
293
  this.innerEditing = false
279
294
 
@@ -281,7 +296,7 @@ export class Editor extends Group implements IEditor {
281
296
  this.innerEditor.unload()
282
297
  this.emitInnerEvent(InnerEditorEvent.CLOSE)
283
298
 
284
- this.editTool.load()
299
+ if (!onlyInnerEditor) this.updateEditTool()
285
300
  this.innerEditor = null
286
301
  }
287
302
  }
@@ -337,14 +352,7 @@ export class Editor extends Group implements IEditor {
337
352
  const { app, leafer, editMask } = this
338
353
  this.targetEventIds = [
339
354
  leafer.on_(RenderEvent.START, this.onRenderStart, this),
340
-
341
- app.on_([
342
- [RenderEvent.CHILD_START, this.onAppRenderStart, this],
343
-
344
- [MoveEvent.BEFORE_MOVE, this.onMove, this, true],
345
- [ZoomEvent.BEFORE_ZOOM, this.onScale, this, true],
346
- [RotateEvent.BEFORE_ROTATE, this.onRotate, this, true],
347
- ])
355
+ app.on_(RenderEvent.CHILD_START, this.onAppRenderStart, this)
348
356
  ]
349
357
  if (editMask.visible) editMask.forceRender()
350
358
  }
@@ -19,6 +19,7 @@ export function targetAttr(fn: IFunction) {
19
19
  const isSelect = key === 'target'
20
20
  if (isSelect) {
21
21
  if (value instanceof Array && value.length > 1 && value[0].locked) value.splice(0, 1) // fix: 单个锁定 + shift多选
22
+ if ((this as IEditor).single) (this as IEditor).element.syncEventer = null // 重置 EditBox.load() 设置
22
23
 
23
24
  const { beforeSelect } = (this as IEditor).config
24
25
  if (beforeSelect) {
@@ -44,8 +45,9 @@ export function mergeConfigAttr() {
44
45
  return (target: IEditor, key: string) => {
45
46
  defineKey(target, key, {
46
47
  get() {
47
- const { config, element, dragPoint } = this, mergeConfig = { ...config } // 实时合并,后期可优化
48
- if (element && element.editConfig) Object.assign(mergeConfig, element.editConfig)
48
+ const { config, element, dragPoint, editBox } = this, mergeConfig = { ...config } // 实时合并,后期可优化
49
+ if (element && element.editConfig) Object.assign(mergeConfig, element.editConfig) // 元素上的配置
50
+ if (editBox.config) Object.assign(mergeConfig, editBox.config) // EditBox 上的配置
49
51
  if (dragPoint) {
50
52
  if (dragPoint.editConfig) Object.assign(mergeConfig, dragPoint.editConfig)
51
53
  if (mergeConfig.editSize === 'font-size') mergeConfig.lockRatio = true // 强制锁定比例
@@ -1,11 +1,10 @@
1
1
  import { IRect, IEventListenerId, IBoundsData, IPointData, IKeyEvent, IGroup, IBox, IBoxInputData, IAlign, IUI, IEditorConfig, IEditorDragStartData, IEventParams, ITransformTool } from '@leafer-ui/interface'
2
- import { Group, Box, Text, AroundHelper, Direction9, ResizeEvent } from '@leafer-ui/draw'
3
- import { DragEvent, PointerEvent, KeyEvent } from '@leafer-ui/core'
2
+ import { Group, Box, Text, AroundHelper, Direction9, ResizeEvent, BoundsHelper } from '@leafer-ui/draw'
3
+ import { DragEvent, PointerEvent, KeyEvent, RotateEvent, ZoomEvent, MoveEvent } from '@leafer-ui/core'
4
4
 
5
5
  import { IEditBox, IEditor, IEditPoint, IEditPointType } from '@leafer-in/interface'
6
6
 
7
- import { updateCursor, updateMoveCursor } from '../editor/cursor'
8
- import { EditorEvent } from '../event/EditorEvent'
7
+ import { updatePointCursor, updateMoveCursor } from '../editor/cursor'
9
8
  import { EditPoint } from './EditPoint'
10
9
  import { EditDataHelper } from '../helper/EditDataHelper'
11
10
 
@@ -17,7 +16,12 @@ export class EditBox extends Group implements IEditBox {
17
16
  public editor: IEditor
18
17
 
19
18
  public dragging: boolean
19
+ public gesturing: boolean
20
+
20
21
  public moving: boolean
22
+ public resizing: boolean
23
+ public rotating: boolean
24
+ public skewing: boolean
21
25
 
22
26
  public view: IGroup = new Group() // 放置默认编辑工具控制点
23
27
 
@@ -38,8 +42,8 @@ export class EditBox extends Group implements IEditBox {
38
42
  public mergedConfig: IEditorConfig
39
43
 
40
44
  public get mergeConfig(): IEditorConfig {
41
- const { config } = this, { mergeConfig } = this.editor
42
- return this.mergedConfig = config ? { ...mergeConfig, ...config } : mergeConfig
45
+ const { config } = this, { mergeConfig, editBox } = this.editor
46
+ return this.mergedConfig = config && (editBox !== this) ? { ...mergeConfig, ...config } : mergeConfig // 可能会出现多个editBox的情况
43
47
  }
44
48
 
45
49
  protected _target: IUI
@@ -58,6 +62,13 @@ export class EditBox extends Group implements IEditBox {
58
62
  public get flippedY(): boolean { return this.scaleY < 0 }
59
63
  public get flippedOne(): boolean { return this.scaleX * this.scaleY < 0 }
60
64
 
65
+ public get canUse(): boolean { return (this.visible && this.view.visible) as boolean } // 编辑框是否处于激活状态
66
+ public get canGesture(): boolean { // 是否支持手势
67
+ if (!this.canUse) return false
68
+ const { moveable, resizeable, rotateable } = this.mergeConfig
69
+ return typeof moveable === 'string' || typeof resizeable === 'string' || typeof rotateable === 'string'
70
+ }
71
+
61
72
  protected __eventIds: IEventListenerId[] = []
62
73
 
63
74
  constructor(editor: IEditor) {
@@ -95,6 +106,7 @@ export class EditBox extends Group implements IEditBox {
95
106
  this.add(view)
96
107
  }
97
108
 
109
+
98
110
  public load(): void {
99
111
  const { target, mergeConfig, single, rect, circle, resizePoints } = this
100
112
  const { stroke, strokeWidth } = mergeConfig
@@ -107,7 +119,7 @@ export class EditBox extends Group implements IEditBox {
107
119
  for (let i = 0; i < 8; i++) {
108
120
  resizeP = resizePoints[i]
109
121
  resizeP.set(this.getPointStyle((i % 2) ? middlePointsStyle[((i - 1) / 2) % middlePointsStyle.length] : pointsStyle[(i / 2) % pointsStyle.length]))
110
- if (!(i % 2)) resizeP.rotation = (i / 2) * 90
122
+ resizeP.rotation = ((i - (i % 2 ? 1 : 0)) / 2) * 90
111
123
  }
112
124
 
113
125
  // rotate
@@ -118,12 +130,12 @@ export class EditBox extends Group implements IEditBox {
118
130
 
119
131
  const syncEventer = single && this.transformTool.editTool
120
132
 
133
+ // 编辑框作为底部虚拟元素, 在 unload() 中重置
121
134
  rect.hittable = !syncEventer
122
135
  rect.syncEventer = syncEventer && this.editor // 单选下 rect 的事件不会冒泡,需要手动传递给editor
123
136
 
124
- // 编辑框作为底部虚拟元素, 在 onSelect 方法移除
125
137
  if (syncEventer) {
126
- target.syncEventer = rect
138
+ target.syncEventer = rect // 在 target 属性装饰中重置
127
139
  this.app.interaction.bottomList = [{ target: rect, proxy: target }]
128
140
  }
129
141
 
@@ -137,14 +149,22 @@ export class EditBox extends Group implements IEditBox {
137
149
  this.updateBounds({ x: 0, y: 0, width, height })
138
150
  }
139
151
 
152
+ public unload(): void {
153
+ this.visible = false
154
+ if (this.app) this.rect.syncEventer = this.app.interaction.bottomList = null
155
+ }
156
+
157
+
140
158
  public updateBounds(bounds: IBoundsData): void {
141
159
  const { editMask } = this.editor
142
160
  const { mergeConfig, single, rect, circle, buttons, resizePoints, rotatePoints, resizeLines } = this
143
- const { middlePoint, resizeable, rotateable, hideOnSmall, editBox, mask } = mergeConfig
161
+ const { middlePoint, resizeable, rotateable, hideOnSmall, editBox, mask, spread } = mergeConfig
144
162
 
145
163
  this.visible = !this.target.locked
146
164
  editMask.visible = mask ? true : 0
147
165
 
166
+ if (spread) BoundsHelper.spread(bounds, spread)
167
+
148
168
  if (this.view.worldOpacity) {
149
169
  const { width, height } = bounds
150
170
  const smallSize = typeof hideOnSmall === 'number' ? hideOnSmall : 10
@@ -175,7 +195,6 @@ export class EditBox extends Group implements IEditBox {
175
195
  if (hideOnSmall && resizeP.width * 2 > width) resizeP.visible = false
176
196
  } else {
177
197
  resizeL.height = height
178
- resizeP.rotation = 90
179
198
  if (hideOnSmall && resizeP.width * 2 > height) resizeP.visible = false
180
199
  }
181
200
  }
@@ -238,11 +257,6 @@ export class EditBox extends Group implements IEditBox {
238
257
  }
239
258
 
240
259
 
241
- public unload(): void {
242
- this.visible = false
243
- }
244
-
245
-
246
260
  public getPointStyle(userStyle?: IBoxInputData): IBoxInputData {
247
261
  const { stroke, strokeWidth, pointFill, pointSize, pointRadius } = this.mergedConfig
248
262
  const defaultStyle = { fill: pointFill, stroke, strokeWidth, around: 'center', strokeAlign: 'center', width: pointSize, height: pointSize, cornerRadius: pointRadius, offsetX: 0, offsetY: 0, editConfig } as IBoxInputData
@@ -259,23 +273,27 @@ export class EditBox extends Group implements IEditBox {
259
273
  return middlePoint instanceof Array ? middlePoint : (middlePoint ? [middlePoint] : this.getPointsStyle())
260
274
  }
261
275
 
262
- protected onSelect(e: EditorEvent): void {
263
- if (e.oldList.length === 1) {
264
- e.oldList[0].syncEventer = null
265
- if (this.app) this.app.interaction.bottomList = null
266
- }
267
- }
268
276
 
269
277
  // drag
270
278
 
271
279
  protected onDragStart(e: DragEvent): void {
272
280
  this.dragging = true
273
281
  const point = this.dragPoint = e.current as IEditPoint, { pointType } = point
274
- const { editor, dragStartData } = this, { target } = this
282
+ const { editor, dragStartData } = this, { target } = this, { moveable, resizeable, rotateable, skewable, hideOnMove } = this.mergeConfig
283
+
284
+ // 确定模式
275
285
  if (point.name === 'rect') {
276
- this.moving = true
277
- editor.opacity = this.mergeConfig.hideOnMove ? 0 : 1 // move
286
+ moveable && (this.moving = true)
287
+ editor.opacity = hideOnMove ? 0 : 1 // move
288
+ } else {
289
+ if (pointType.includes('rotate') || e.metaKey || e.ctrlKey || !resizeable) {
290
+ rotateable && (this.rotating = true)
291
+ if (pointType === 'resize-rotate') resizeable && (this.resizing = true)
292
+ else if (point.name === 'resize-line') skewable && (this.skewing = true), this.rotating = false
293
+ } else if (pointType === 'resize') resizeable && (this.resizing = true)
294
+ if (pointType === 'skew') skewable && (this.skewing = true)
278
295
  }
296
+
279
297
  dragStartData.x = e.x
280
298
  dragStartData.y = e.y
281
299
  dragStartData.point = { x: target.x, y: target.y } // 用于移动
@@ -285,37 +303,73 @@ export class EditBox extends Group implements IEditBox {
285
303
  }
286
304
 
287
305
  protected onDragEnd(e: DragEvent): void {
288
- this.dragging = false
289
306
  this.dragPoint = null
290
- this.moving = false
307
+ this.resetDoing()
291
308
  const { name, pointType } = e.current as IEditPoint
292
309
  if (name === 'rect') this.editor.opacity = 1 // move
293
310
  if (pointType && pointType.includes('resize')) ResizeEvent.resizingKeys = null
294
311
  }
295
312
 
296
313
  protected onDrag(e: DragEvent): void {
297
- const { transformTool } = this, point = e.current as IEditPoint
298
- if (point.name === 'rect') {
314
+ const { transformTool, moving, resizing, rotating, skewing } = this
315
+ if (moving) {
299
316
  transformTool.onMove(e)
300
317
  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)
318
+ } else if (resizing || rotating || skewing) {
319
+ const point = e.current as IEditPoint
320
+ if (point.pointType) this.enterPoint = point// 防止变化
321
+ if (rotating) transformTool.onRotate(e)
322
+ if (resizing) transformTool.onScale(e)
323
+ if (skewing) transformTool.onSkew(e)
324
+ updatePointCursor(this, e)
325
+ }
326
+ }
327
+
328
+ protected resetDoing(): void {
329
+ if (this.canUse) this.dragging = this.gesturing = this.moving = this.resizing = this.rotating = this.skewing = false
330
+ }
331
+
332
+ // 手势控制元素
333
+
334
+ public onMove(e: MoveEvent): void {
335
+ if (this.canGesture && e.moveType !== 'drag') {
336
+ e.stop()
337
+ if (typeof this.mergeConfig.moveable === 'string') {
338
+ this.gesturing = this.moving = true
339
+ this.transformTool.onMove(e)
340
+ }
341
+ }
342
+ }
343
+
344
+ public onScale(e: ZoomEvent): void {
345
+ if (this.canGesture) {
346
+ e.stop()
347
+ if (typeof this.mergeConfig.resizeable === 'string') {
348
+ this.gesturing = this.resizing = true
349
+ this.transformTool.onScale(e)
350
+ }
351
+ }
352
+ }
353
+
354
+ public onRotate(e: RotateEvent): void {
355
+ if (this.canGesture) {
356
+ e.stop()
357
+ if (typeof this.mergeConfig.rotateable === 'string') {
358
+ this.gesturing = this.rotating = true
359
+ this.transformTool.onRotate(e)
360
+ }
309
361
  }
310
362
  }
311
363
 
364
+ // 键盘
365
+
312
366
  protected onKey(e: KeyEvent): void {
313
- updateCursor(this, e)
367
+ updatePointCursor(this, e)
314
368
  }
315
369
 
316
370
  public onArrow(e: IKeyEvent): void {
317
- const { editor } = this
318
- if (editor.editing && this.mergeConfig.keyEvent) {
371
+ const { editor, transformTool } = this
372
+ if (this.canUse && editor.editing && this.mergeConfig.keyEvent) {
319
373
  let x = 0, y = 0
320
374
  const distance = e.shiftKey ? 10 : 1
321
375
  switch (e.code) {
@@ -331,7 +385,7 @@ export class EditBox extends Group implements IEditBox {
331
385
  case 'ArrowRight':
332
386
  x = distance
333
387
  }
334
- if (x || y) editor.move(x, y)
388
+ if (x || y) transformTool.move(x, y)
335
389
  }
336
390
  }
337
391
 
@@ -376,7 +430,7 @@ export class EditBox extends Group implements IEditBox {
376
430
  [DragEvent.END, this.onDragEnd, this],
377
431
  [PointerEvent.LEAVE, () => { this.enterPoint = null }],
378
432
  ]
379
- if (point.name !== 'circle') events.push([PointerEvent.ENTER, (e: PointerEvent) => { this.enterPoint = point, updateCursor(this, e) }])
433
+ if (point.name !== 'circle') events.push([PointerEvent.ENTER, (e: PointerEvent) => { this.enterPoint = point, updatePointCursor(this, e) }])
380
434
  this.__eventIds.push(point.on_(events))
381
435
  }
382
436
 
@@ -384,8 +438,6 @@ export class EditBox extends Group implements IEditBox {
384
438
  const { rect, editor, __eventIds: events } = this
385
439
 
386
440
  events.push(
387
- editor.on_(EditorEvent.SELECT, this.onSelect, this),
388
-
389
441
  rect.on_([
390
442
  [DragEvent.START, this.onDragStart, this],
391
443
  [DragEvent.DRAG, this.onDrag, this],
@@ -401,7 +453,13 @@ export class EditBox extends Group implements IEditBox {
401
453
  events.push(
402
454
  editor.app.on_([
403
455
  [[KeyEvent.HOLD, KeyEvent.UP], this.onKey, this],
404
- [KeyEvent.DOWN, this.onArrow, this]
456
+ [KeyEvent.DOWN, this.onArrow, this],
457
+ [MoveEvent.BEFORE_MOVE, this.onMove, this, true],
458
+ [ZoomEvent.BEFORE_ZOOM, this.onScale, this, true],
459
+ [RotateEvent.BEFORE_ROTATE, this.onRotate, this, true],
460
+ [MoveEvent.END, this.resetDoing, this],
461
+ [ZoomEvent.END, this.resetDoing, this],
462
+ [RotateEvent.END, this.resetDoing, this],
405
463
  ])
406
464
  )
407
465
  })
@@ -54,16 +54,16 @@ export class EditSelect extends Group implements IEditSelect {
54
54
 
55
55
  protected onSelect(): void {
56
56
  if (this.running) {
57
- const { mergeConfig, list } = this.editor
58
- const { stroke, strokeWidth, selectedStyle } = mergeConfig
59
- this.targetStroker.setTarget(list, { stroke, strokeWidth: Math.max(1, strokeWidth / 2), ...(selectedStyle || {}) })
57
+ this.targetStroker.setTarget(this.editor.list)
60
58
  this.hoverStroker.target = null
61
59
  }
62
60
  }
63
61
 
64
62
  public update(): void {
65
63
  this.hoverStroker.update()
66
- this.targetStroker.update()
64
+
65
+ const { stroke, strokeWidth, selectedStyle } = this.editor.mergedConfig
66
+ this.targetStroker.update({ stroke, strokeWidth: strokeWidth && Math.max(1, strokeWidth / 2), ...(selectedStyle || {}) })
67
67
  }
68
68
 
69
69
  // move / down
@@ -27,16 +27,17 @@ export class Stroker extends UI implements IStroker {
27
27
  this.strokeAlign = 'center'
28
28
  }
29
29
 
30
- public setTarget(target: IUI | IUI[], style: IRectInputData): void {
31
- this.set(style)
30
+ public setTarget(target: IUI | IUI[], style?: IRectInputData): void {
31
+ if (style) this.set(style)
32
32
  this.target = target
33
33
  this.update()
34
34
  }
35
35
 
36
- public update(): void {
36
+ public update(style?: IRectInputData): void {
37
37
  const { list } = this
38
38
  if (list.length) {
39
39
  setListWithFn(bounds, list, worldBounds)
40
+ if (style) this.set(style)
40
41
  this.set(bounds)
41
42
  this.visible = true
42
43
  } else this.visible = 0
@@ -8,23 +8,26 @@ import { EditDataHelper } from '../helper/EditDataHelper'
8
8
 
9
9
  const cacheCursors: IObject = {}
10
10
 
11
- export function updateCursor(editBox: IEditBox, e: IUIEvent): void {
12
- const { enterPoint: point } = editBox
13
- if (!point || !editBox.editor.editing || !editBox.visible) return
11
+ export function updatePointCursor(editBox: IEditBox, e: IUIEvent): void {
12
+ const { enterPoint: point, dragging, skewing, resizing, flippedX, flippedY } = editBox
13
+ if (!point || !editBox.editor.editing || !editBox.canUse) return
14
14
  if (point.name === 'circle') return // 独立旋转按钮
15
15
  if (point.pointType === 'button') { // 普通按钮
16
16
  if (!point.cursor) point.cursor = 'pointer'
17
17
  return
18
18
  }
19
19
 
20
- let { rotation, flippedX, flippedY } = editBox
20
+ let { rotation } = editBox
21
21
  const { pointType } = point, { resizeCursor, rotateCursor, skewCursor, resizeable, rotateable, skewable } = editBox.mergeConfig
22
22
 
23
23
  let showResize = pointType.includes('resize')
24
24
  if (showResize && rotateable && (e.metaKey || e.ctrlKey || !resizeable)) showResize = false
25
25
  const showSkew = skewable && !showResize && (point.name === 'resize-line' || pointType === 'skew')
26
26
 
27
- const cursor = showSkew ? skewCursor : (showResize ? resizeCursor : rotateCursor)
27
+ const cursor = dragging
28
+ ? (skewing ? skewCursor : (resizing ? resizeCursor : rotateCursor))
29
+ : (showSkew ? skewCursor : (showResize ? resizeCursor : rotateCursor))
30
+
28
31
  rotation += (EditDataHelper.getFlipDirection(point.direction, flippedX, flippedY) + 1) * 45
29
32
  rotation = Math.round(MathHelper.formatRotation(rotation, true) / 2) * 2
30
33
 
@@ -40,7 +43,7 @@ export function updateCursor(editBox: IEditBox, e: IUIEvent): void {
40
43
 
41
44
  export function updateMoveCursor(editBox: IEditBox): void {
42
45
  const { moveCursor, moveable } = editBox.mergeConfig
43
- editBox.rect.cursor = moveable ? moveCursor : undefined
46
+ if (editBox.canUse) editBox.rect.cursor = moveable ? moveCursor : undefined
44
47
  }
45
48
 
46
49
 
@@ -16,7 +16,8 @@ export function onTarget(editor: IEditor, oldValue: IUI | IUI[]): void {
16
16
  editor.leafList.reset()
17
17
  }
18
18
 
19
- editor.closeInnerEditor()
19
+ editor.closeInnerEditor(true)
20
+ editor.unloadEditTool()
20
21
 
21
22
  const data = { editor, value: target, oldValue }
22
23
  editor.emitEvent(new EditorEvent(EditorEvent.SELECT, data))
@@ -116,14 +116,18 @@ export const EditDataHelper = {
116
116
 
117
117
  if (dragBounds) {
118
118
  const allowBounds = dragBounds === 'parent' ? target.parent.boxBounds : dragBounds
119
- const localBounds = new Bounds(target.__localBoxBounds)
120
- localBounds.scaleOf(target.getLocalPointByInner(origin), scaleX, scaleY)
121
-
122
- if (!BoundsHelper.includes(allowBounds, localBounds)) {
123
- const realBounds = localBounds.getIntersect(allowBounds)
124
- const fitScaleX = realBounds.width / localBounds.width, fitScaleY = realBounds.height / localBounds.height
125
- if (useScaleX) scaleX *= fitScaleX
126
- if (useScaleY) scaleY *= fitScaleY // 后续需优化带旋转的场景
119
+ const childBounds = new Bounds(target.__localBoxBounds)
120
+
121
+ if (BoundsHelper.includes(new Bounds(allowBounds).spread(0.1), childBounds)) {
122
+
123
+ childBounds.scaleOf(target.getLocalPointByInner(origin), scaleX, scaleY)
124
+
125
+ if (!BoundsHelper.includes(allowBounds, childBounds)) {
126
+ const realBounds = childBounds.getIntersect(allowBounds)
127
+ const fitScaleX = realBounds.width / childBounds.width, fitScaleY = realBounds.height / childBounds.height
128
+ if (useScaleX) scaleX *= fitScaleX
129
+ if (useScaleY) scaleY *= fitScaleY // 后续需优化带旋转的场景
130
+ }
127
131
  }
128
132
  }
129
133
 
package/src/index.ts CHANGED
@@ -47,7 +47,7 @@ Creator.editor = function (options?: IEditorConfig, app?: IApp): IEditor {
47
47
  Box.addAttr('textBox', false, dataType)
48
48
 
49
49
  UI.addAttr('editConfig', undefined, dataType)
50
- UI.addAttr('editOuter', (ui: UI) => ui.__.__isLinePath ? 'LineEditTool' : 'EditTool', dataType)
50
+ UI.addAttr('editOuter', (ui: UI) => { ui.updateLayout(); return ui.__.__isLinePath ? 'LineEditTool' : 'EditTool' }, dataType) // fix: Line 需要更新布局才能精准确定
51
51
 
52
52
  UI.addAttr('editInner', 'PathEditor', dataType)
53
53
  Group.addAttr('editInner', '', dataType) // 必须设为空
@@ -1,5 +1,5 @@
1
1
  import { IEvent, IPointData, IAlign, IAxis, IFunction, IMatrix } from '@leafer-ui/interface'
2
- import { MathHelper, Matrix, LeafHelper } from '@leafer-ui/draw'
2
+ import { MathHelper, Matrix, LeafHelper, AroundHelper } from '@leafer-ui/draw'
3
3
  import { DragEvent, RotateEvent, ZoomEvent, MoveEvent } from '@leafer-ui/core'
4
4
 
5
5
  import { IEditBox, IEditPoint, IEditTool, IEditorScaleEvent, ISimulateElement, IEditorMoveEvent, IEditorRotateEvent, IEditorSkewEvent } from '@leafer-in/interface'
@@ -23,17 +23,12 @@ export class TransformTool implements ITransformTool { // Editor use
23
23
 
24
24
  public onMove(e: DragEvent | MoveEvent): void {
25
25
 
26
- const { target, mergeConfig, dragStartData } = this.editBox
26
+ const { target, dragStartData } = this.editBox
27
27
 
28
28
  if (e instanceof MoveEvent) {
29
29
 
30
- if (e.moveType !== 'drag') {
31
- const { moveable, resizeable } = mergeConfig
32
- const move = e.getLocalMove(target)
33
-
34
- if (moveable === 'move') e.stop(), this.move(move.x, move.y)
35
- else if (resizeable === 'zoom') e.stop()
36
- }
30
+ const move = e.getLocalMove(target)
31
+ this.move(move.x, move.y)
37
32
 
38
33
  } else {
39
34
 
@@ -52,11 +47,11 @@ export class TransformTool implements ITransformTool { // Editor use
52
47
  public onScale(e: DragEvent | ZoomEvent): void {
53
48
 
54
49
  const { target, mergeConfig, single, dragStartData } = this.editBox
55
- let { around, lockRatio, resizeable, flipable, editSize } = mergeConfig
50
+ let { around, lockRatio, flipable, editSize } = mergeConfig
56
51
 
57
52
  if (e instanceof ZoomEvent) {
58
53
 
59
- if (resizeable === 'zoom') e.stop(), this.scaleOf(target.getBoxPoint(e), e.scale, e.scale)
54
+ this.scaleOf(target.getBoxPoint(e), e.scale, e.scale)
60
55
 
61
56
  } else {
62
57
 
@@ -78,31 +73,24 @@ export class TransformTool implements ITransformTool { // Editor use
78
73
  public onRotate(e: DragEvent | RotateEvent): void {
79
74
 
80
75
  const { target, mergeConfig, dragStartData } = this.editBox
81
- const { skewable, rotateable, around, rotateGap } = mergeConfig
82
- const { direction, name } = e.current as IEditPoint
83
-
84
- if (skewable && name === 'resize-line') return this.onSkew(e as DragEvent)
76
+ const { around, rotateAround, rotateGap } = mergeConfig
77
+ const { direction } = e.current as IEditPoint
85
78
 
86
79
  let origin: IPointData, rotation: number
87
80
 
88
81
  if (e instanceof RotateEvent) {
89
82
 
90
- if (rotateable === 'rotate') e.stop(), rotation = e.rotation, origin = target.getBoxPoint(e)
91
- else return
92
-
93
- if (target.scaleX * target.scaleY < 0) rotation = -rotation // flippedOne
83
+ rotation = e.rotation
84
+ origin = rotateAround ? AroundHelper.getPoint(rotateAround, target.boxBounds) : target.getBoxPoint(e)
94
85
 
95
86
  } else {
96
87
 
97
- const data = EditDataHelper.getRotateData(target, direction, e, dragStartData, e.shiftKey ? null : (target.around || target.origin || around || 'center'))
98
- rotation = data.rotation
88
+ const data = EditDataHelper.getRotateData(target, direction, e, dragStartData, e.shiftKey ? null : (rotateAround || target.around || target.origin || around || 'center'))
89
+ rotation = dragStartData.rotation + data.rotation - target.rotation
99
90
  origin = data.origin
100
91
 
101
92
  }
102
93
 
103
- if (target.scaleX * target.scaleY < 0) rotation = -rotation // flippedOne
104
- if (e instanceof DragEvent) rotation = dragStartData.rotation + rotation - target.rotation
105
-
106
94
  rotation = MathHelper.float(MathHelper.getGapRotation(rotation, rotateGap, target.rotation), 2)
107
95
  if (!rotation) return
108
96