@leafer-in/editor 1.4.2 → 1.5.1

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.4.2",
3
+ "version": "1.5.1",
4
4
  "description": "@leafer-in/editor",
5
5
  "author": "Chao (Leafer) Wan",
6
6
  "license": "MIT",
@@ -34,9 +34,9 @@
34
34
  "leaferjs"
35
35
  ],
36
36
  "peerDependencies": {
37
- "@leafer-ui/core": "^1.4.2",
38
- "@leafer-in/resize": "^1.4.2",
39
- "@leafer-ui/interface": "^1.4.2",
40
- "@leafer-in/interface": "^1.4.2"
37
+ "@leafer-ui/core": "^1.5.1",
38
+ "@leafer-in/resize": "^1.5.1",
39
+ "@leafer-ui/interface": "^1.5.1",
40
+ "@leafer-in/interface": "^1.5.1"
41
41
  }
42
42
  }
package/src/Editor.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { IGroupInputData, IUI, IEventListenerId, IPointData, ILeafList, IEditSize, IGroup, IObject, IAlign, IAxis, IFunction, ILayoutBoundsData, IMatrix } from '@leafer-ui/interface'
2
- import { Group, DataHelper, MathHelper, LeafList, Matrix, RenderEvent, LeafHelper, Direction9 } from '@leafer-ui/draw'
1
+ import { IGroupInputData, IUI, IEventListenerId, IPointData, ILeafList, IEditSize, IGroup, IObject, IAlign, IAxis, IFunction, IMatrix } from '@leafer-ui/interface'
2
+ import { Group, DataHelper, MathHelper, LeafList, Matrix, RenderEvent, LeafHelper, Direction9, isNull } from '@leafer-ui/draw'
3
3
  import { DragEvent, RotateEvent, KeyEvent, ZoomEvent, MoveEvent, Plugin } from '@leafer-ui/core'
4
4
 
5
- import { IEditBox, IEditPoint, IEditor, IEditorConfig, IEditTool, IEditorScaleEvent, IInnerEditor, ISimulateElement } from '@leafer-in/interface'
5
+ import { IEditBox, IEditPoint, IEditor, IEditorConfig, IEditTool, IEditorScaleEvent, IInnerEditor, ISimulateElement, IEditorMoveEvent, IEditorRotateEvent, IEditorSkewEvent } from '@leafer-in/interface'
6
6
 
7
7
  import { EditorMoveEvent } from './event/EditorMoveEvent'
8
8
  import { EditorScaleEvent } from './event/EditorScaleEvent'
@@ -32,8 +32,17 @@ export class Editor extends Group implements IEditor {
32
32
  public config = DataHelper.clone(config) as IEditorConfig
33
33
 
34
34
  public get mergeConfig(): IEditorConfig {
35
- const { element, config } = this
36
- return this.single && element.editConfig ? { ...config, ...element.editConfig } : config // 实时合并,后期可优化
35
+ const { config, element, dragPoint } = this, mergeConfig = { ...config } // 实时合并,后期可优化
36
+ if (element && element.editConfig) Object.assign(mergeConfig, element.editConfig)
37
+ if (dragPoint) {
38
+ if (dragPoint.editConfig) Object.assign(mergeConfig, dragPoint.editConfig)
39
+ if (mergeConfig.editSize === 'font-size') mergeConfig.lockRatio = true // 强制锁定比例
40
+ if (dragPoint.pointType === 'resize-rotate') {
41
+ mergeConfig.around || (mergeConfig.around = 'center')
42
+ isNull(mergeConfig.lockRatio) && (mergeConfig.lockRatio = true)
43
+ }
44
+ }
45
+ return mergeConfig
37
46
  }
38
47
 
39
48
  @targetAttr(onHover)
@@ -61,6 +70,7 @@ export class Editor extends Group implements IEditor {
61
70
 
62
71
  public get dragging(): boolean { return this.editBox.dragging }
63
72
  public get moving(): boolean { return this.editBox.moving }
73
+ public get dragPoint(): IEditPoint { return this.editBox.dragPoint }
64
74
 
65
75
  // 组件
66
76
 
@@ -78,9 +88,6 @@ export class Editor extends Group implements IEditor {
78
88
  public selector: EditSelect = new EditSelect(this)
79
89
  public editMask: EditMask = new EditMask(this)
80
90
 
81
- public dragStartPoint: IPointData
82
- public dragStartBounds: ILayoutBoundsData
83
-
84
91
  public targetEventIds: IEventListenerId[] = []
85
92
 
86
93
 
@@ -180,7 +187,7 @@ export class Editor extends Group implements IEditor {
180
187
  else total.x = 0
181
188
  }
182
189
 
183
- this.move(DragEvent.getValidMove(this.element, this.dragStartPoint, total))
190
+ this.move(DragEvent.getValidMove(this.element, this.editBox.dragStartData.point, total))
184
191
 
185
192
  }
186
193
 
@@ -200,7 +207,7 @@ export class Editor extends Group implements IEditor {
200
207
 
201
208
  if (e.shiftKey || element.lockRatio) lockRatio = true
202
209
 
203
- const data = EditDataHelper.getScaleData(element, this.dragStartBounds, direction, e.getInnerTotal(element), lockRatio, EditDataHelper.getAround(around, e.altKey), flipable, this.multiple || editSize === 'scale')
210
+ const data = EditDataHelper.getScaleData(element, this.editBox.dragStartData.bounds, direction, e.getInnerTotal(element), lockRatio, EditDataHelper.getAround(around, e.altKey), flipable, this.multiple || editSize === 'scale')
204
211
 
205
212
  if (this.editTool.onScaleWithDrag) {
206
213
  data.drag = e
@@ -218,7 +225,7 @@ export class Editor extends Group implements IEditor {
218
225
  const { direction, name } = e.current as IEditPoint
219
226
  if (skewable && name === 'resize-line') return this.onSkew(e as DragEvent)
220
227
 
221
- const { element } = this
228
+ const { element } = this, { dragStartData } = this.editBox
222
229
  let origin: IPointData, rotation: number
223
230
 
224
231
  if (e instanceof RotateEvent) {
@@ -226,21 +233,23 @@ export class Editor extends Group implements IEditor {
226
233
  if (rotateable === 'rotate') e.stop(), rotation = e.rotation, origin = element.getBoxPoint(e)
227
234
  else return
228
235
 
236
+ if (element.scaleX * element.scaleY < 0) rotation = -rotation // flippedOne
237
+
229
238
  } else {
230
239
 
231
- const last = { x: e.x - e.moveX, y: e.y - e.moveY }
232
- const data = EditDataHelper.getRotateData(element.boxBounds, direction, e.getBoxPoint(element), element.getBoxPoint(last), e.shiftKey ? null : (element.around || element.origin || around || 'center'))
240
+ const data = EditDataHelper.getRotateData(element.boxBounds, direction, e.getBoxPoint(element), element.getBoxPoint(dragStartData), e.shiftKey ? null : (element.around || element.origin || around || 'center'))
233
241
  rotation = data.rotation
234
242
  origin = data.origin
235
243
 
236
244
  }
237
245
 
238
- rotation = MathHelper.getGapRotation(rotation, rotateGap, element.rotation)
239
- if (!rotation) return
240
-
241
246
  if (element.scaleX * element.scaleY < 0) rotation = -rotation // flippedOne
247
+ if (e instanceof DragEvent) rotation = dragStartData.rotation + rotation - element.rotation
242
248
 
243
- this.rotateOf(origin, MathHelper.float(rotation, 2))
249
+ rotation = MathHelper.float(MathHelper.getGapRotation(rotation, rotateGap, element.rotation), 2)
250
+ if (!rotation) return
251
+
252
+ this.rotateOf(origin, rotation)
244
253
  }
245
254
 
246
255
 
@@ -261,11 +270,12 @@ export class Editor extends Group implements IEditor {
261
270
  const { element } = this
262
271
  if (!this.checkTransform('moveable')) return
263
272
 
264
-
265
273
  const world = element.getWorldPointByLocal(typeof x === 'object' ? { ...x } : { x, y }, null, true)
266
274
  if (this.multiple) element.safeChange(() => element.move(x, y))
267
- const event = new EditorMoveEvent(EditorMoveEvent.MOVE, { target: element, editor: this, moveX: world.x, moveY: world.y })
275
+ const data: IEditorMoveEvent = { target: element, editor: this, moveX: world.x, moveY: world.y }
268
276
 
277
+ this.emitEvent(new EditorMoveEvent(EditorMoveEvent.BEFORE_MOVE, data))
278
+ const event = new EditorMoveEvent(EditorMoveEvent.MOVE, data)
269
279
  this.editTool.onMove(event)
270
280
  this.emitEvent(event)
271
281
  }
@@ -274,8 +284,10 @@ export class Editor extends Group implements IEditor {
274
284
  if (!this.checkTransform('resizeable')) return
275
285
 
276
286
  const { element } = this
277
- const event = new EditorScaleEvent(EditorScaleEvent.SCALE, { ...data, target: element, editor: this, worldOrigin: element.getWorldPoint(data.origin) })
287
+ data = { ...data, target: element, editor: this, worldOrigin: element.getWorldPoint(data.origin) }
278
288
 
289
+ this.emitEvent(new EditorScaleEvent(EditorScaleEvent.BEFORE_SCALE, data))
290
+ const event = new EditorScaleEvent(EditorScaleEvent.SCALE, data)
279
291
  this.editTool.onScaleWithDrag(event)
280
292
  this.emitEvent(event)
281
293
  }
@@ -287,8 +299,10 @@ export class Editor extends Group implements IEditor {
287
299
  const { element } = this
288
300
  const worldOrigin = this.getWorldOrigin(origin)
289
301
  const transform = this.multiple && this.getChangedTransform(() => element.safeChange(() => element.scaleOf(origin, scaleX, scaleY)))
290
- const event = new EditorScaleEvent(EditorScaleEvent.SCALE, { target: element, editor: this, worldOrigin, scaleX, scaleY, transform })
302
+ const data: IEditorScaleEvent = { target: element, editor: this, worldOrigin, scaleX, scaleY, transform }
291
303
 
304
+ this.emitEvent(new EditorScaleEvent(EditorScaleEvent.BEFORE_SCALE, data))
305
+ const event = new EditorScaleEvent(EditorScaleEvent.SCALE, data)
292
306
  this.editTool.onScale(event)
293
307
  this.emitEvent(event)
294
308
  }
@@ -299,8 +313,10 @@ export class Editor extends Group implements IEditor {
299
313
  const { element } = this
300
314
  const worldOrigin = this.getWorldOrigin('center')
301
315
  const transform = this.multiple ? this.getChangedTransform(() => element.safeChange(() => element.flip(axis))) : new Matrix(LeafHelper.getFlipTransform(element, axis))
302
- const event = new EditorScaleEvent(EditorScaleEvent.SCALE, { target: element, editor: this, worldOrigin, scaleX: axis === 'x' ? -1 : 1, scaleY: axis === 'y' ? -1 : 1, transform })
316
+ const data: IEditorScaleEvent = { target: element, editor: this, worldOrigin, scaleX: axis === 'x' ? -1 : 1, scaleY: axis === 'y' ? -1 : 1, transform }
303
317
 
318
+ this.emitEvent(new EditorScaleEvent(EditorScaleEvent.BEFORE_SCALE, data))
319
+ const event = new EditorScaleEvent(EditorScaleEvent.SCALE, data)
304
320
  this.editTool.onScale(event)
305
321
  this.emitEvent(event)
306
322
  }
@@ -311,8 +327,10 @@ export class Editor extends Group implements IEditor {
311
327
  const { element } = this
312
328
  const worldOrigin = this.getWorldOrigin(origin)
313
329
  const transform = this.multiple && this.getChangedTransform(() => element.safeChange(() => element.rotateOf(origin, rotation)))
314
- const event = new EditorRotateEvent(EditorRotateEvent.ROTATE, { target: element, editor: this, worldOrigin, rotation, transform })
330
+ const data: IEditorRotateEvent = { target: element, editor: this, worldOrigin, rotation, transform }
315
331
 
332
+ this.emitEvent(new EditorRotateEvent(EditorRotateEvent.BEFORE_ROTATE, data))
333
+ const event = new EditorRotateEvent(EditorRotateEvent.ROTATE, data)
316
334
  this.editTool.onRotate(event)
317
335
  this.emitEvent(event)
318
336
  }
@@ -323,8 +341,10 @@ export class Editor extends Group implements IEditor {
323
341
  const { element } = this
324
342
  const worldOrigin = this.getWorldOrigin(origin)
325
343
  const transform = this.multiple && this.getChangedTransform(() => element.safeChange(() => element.skewOf(origin, skewX, skewY)))
326
- const event = new EditorSkewEvent(EditorSkewEvent.SKEW, { target: element, editor: this, worldOrigin, skewX, skewY, transform })
344
+ const data: IEditorSkewEvent = { target: element, editor: this, worldOrigin, skewX, skewY, transform }
327
345
 
346
+ this.emitEvent(new EditorSkewEvent(EditorSkewEvent.BEFORE_SKEW, data))
347
+ const event = new EditorSkewEvent(EditorSkewEvent.SKEW, data)
328
348
  this.editTool.onSkew(event)
329
349
  this.emitEvent(event)
330
350
  }
@@ -349,6 +369,7 @@ export class Editor extends Group implements IEditor {
349
369
 
350
370
  public group(userGroup?: IGroup | IGroupInputData): IGroup {
351
371
  if (this.multiple) {
372
+ this.emitGroupEvent(EditorGroupEvent.BEFORE_GROUP)
352
373
  this.target = EditorHelper.group(this.list, this.element, userGroup)
353
374
  this.emitGroupEvent(EditorGroupEvent.GROUP, this.target as IGroup)
354
375
  }
@@ -366,12 +387,14 @@ export class Editor extends Group implements IEditor {
366
387
  }
367
388
 
368
389
  public openGroup(group: IGroup): void {
390
+ this.emitGroupEvent(EditorGroupEvent.BEFORE_OPEN, group)
369
391
  this.openedGroupList.add(group)
370
392
  group.hitChildren = true
371
393
  this.emitGroupEvent(EditorGroupEvent.OPEN, group)
372
394
  }
373
395
 
374
396
  public closeGroup(group: IGroup): void {
397
+ this.emitGroupEvent(EditorGroupEvent.BEFORE_CLOSE, group)
375
398
  this.openedGroupList.remove(group)
376
399
  group.hitChildren = false
377
400
  this.emitGroupEvent(EditorGroupEvent.CLOSE, group)
@@ -398,10 +421,10 @@ export class Editor extends Group implements IEditor {
398
421
  }
399
422
  }
400
423
 
401
- public emitGroupEvent(type: string, group: IGroup): void {
424
+ public emitGroupEvent(type: string, group?: IGroup): void {
402
425
  const event = new EditorGroupEvent(type, { editTarget: group })
403
426
  this.emitEvent(event)
404
- group.emitEvent(event)
427
+ if (group) group.emitEvent(event)
405
428
  }
406
429
 
407
430
  // inner
package/src/config.ts CHANGED
@@ -26,6 +26,7 @@ export const config: IEditorConfig = {
26
26
  skewCursor: { url: skewSVG, x: 12, y: 12 },
27
27
 
28
28
  selector: true,
29
+ editBox: true,
29
30
  hover: true,
30
31
  select: 'press',
31
32
  openInner: 'double',
@@ -1,6 +1,10 @@
1
- import { IFunction, ILeaf, IObject } from '@leafer-ui/interface'
1
+ import { IFunction, ILeaf, IObject, IUI, } from '@leafer-ui/interface'
2
+ import { IEditor } from '@leafer-in/interface'
2
3
  import { defineKey } from '@leafer-ui/draw'
3
4
 
5
+ import { EditorEvent } from '../event/EditorEvent'
6
+
7
+
4
8
 
5
9
  export function targetAttr(fn: IFunction) {
6
10
  return (target: ILeaf, key: string) => {
@@ -9,7 +13,11 @@ export function targetAttr(fn: IFunction) {
9
13
  get() { return (this as IObject)[privateKey] },
10
14
  set(value: unknown) {
11
15
  const old = (this as IObject)[privateKey]
12
- if (old !== value) (this as IObject)[privateKey] = value, fn(this, old)
16
+ if (old !== value) {
17
+ const type = key === 'target' ? EditorEvent.BEFORE_SELECT : EditorEvent.BEFORE_HOVER
18
+ if (this.hasEvent(type)) this.emitEvent(new EditorEvent(type, { editor: this as IEditor, value: value as IUI, oldValue: old }));
19
+ (this as IObject)[privateKey] = value, fn(this, old)
20
+ }
13
21
  }
14
22
  } as ThisType<ILeaf>)
15
23
  }
@@ -1,4 +1,4 @@
1
- import { IRect, IEventListenerId, IBoundsData, IPointData, IKeyEvent, IGroup, IBox, IBoxInputData, IAlign, IUI, IEditorConfig } from '@leafer-ui/interface'
1
+ import { IRect, IEventListenerId, IBoundsData, IPointData, IKeyEvent, IGroup, IBox, IBoxInputData, IAlign, IUI, IEditorConfig, IEditorDragStartData } from '@leafer-ui/interface'
2
2
  import { Group, Box, Text, AroundHelper, Direction9 } from '@leafer-ui/draw'
3
3
  import { DragEvent, PointerEvent } from '@leafer-ui/core'
4
4
 
@@ -10,7 +10,7 @@ import { EditPoint } from './EditPoint'
10
10
  import { EditDataHelper } from '../helper/EditDataHelper'
11
11
 
12
12
 
13
- const fourDirection = ['top', 'right', 'bottom', 'left']
13
+ const fourDirection = ['top', 'right', 'bottom', 'left'], editConfig: IEditorConfig = undefined
14
14
 
15
15
  export class EditBox extends Group implements IEditBox {
16
16
 
@@ -28,14 +28,17 @@ export class EditBox extends Group implements IEditBox {
28
28
  public rotatePoints: IEditPoint[] = [] // topLeft, top, topRight, right, bottomRight, bottom, bottomLeft, left
29
29
  public resizeLines: IEditPoint[] = [] // top, right, bottom, left
30
30
 
31
+ public enterPoint: IEditPoint
32
+ public dragPoint: IEditPoint // 正在拖拽的控制点
33
+
34
+ public dragStartData = {} as IEditorDragStartData
35
+
31
36
  // fliped
32
37
  public get flipped(): boolean { return this.flippedX || this.flippedY }
33
38
  public get flippedX(): boolean { return this.scaleX < 0 }
34
39
  public get flippedY(): boolean { return this.scaleY < 0 }
35
40
  public get flippedOne(): boolean { return this.scaleX * this.scaleY < 0 }
36
41
 
37
- public enterPoint: IEditPoint
38
-
39
42
  protected __eventIds: IEventListenerId[] = []
40
43
 
41
44
  constructor(editor: IEditor) {
@@ -93,7 +96,7 @@ export class EditBox extends Group implements IEditBox {
93
96
  circle.set(this.getPointStyle(mergeConfig.circle || mergeConfig.rotatePoint || pointsStyle[0]))
94
97
 
95
98
  // rect
96
- rect.set({ stroke, strokeWidth, ...(mergeConfig.rect || {}) })
99
+ rect.set({ stroke, strokeWidth, editConfig, ...(mergeConfig.rect || {}) })
97
100
  rect.hittable = !single
98
101
  rect.syncEventer = single && this.editor // 单选下 rect 的事件不会冒泡,需要手动传递给editor
99
102
 
@@ -105,16 +108,16 @@ export class EditBox extends Group implements IEditBox {
105
108
  }
106
109
 
107
110
  public update(bounds: IBoundsData): void {
108
- this.visible = !this.editor.element.locked
111
+ const { mergeConfig, element, multiple } = this.editor
112
+ const { middlePoint, resizeable, rotateable, hideOnSmall, editBox } = mergeConfig
113
+ this.visible = !element.locked
109
114
 
110
115
  if (this.view.worldOpacity) {
111
- const { mergeConfig } = this.editor
112
116
  const { width, height } = bounds
113
117
  const { rect, circle, buttons, resizePoints, rotatePoints, resizeLines } = this
114
- const { middlePoint, resizeable, rotateable, hideOnSmall } = mergeConfig
115
118
 
116
119
  const smallSize = typeof hideOnSmall === 'number' ? hideOnSmall : 10
117
- const showPoints = !(hideOnSmall && width < smallSize && height < smallSize)
120
+ const showPoints = editBox && !(hideOnSmall && width < smallSize && height < smallSize)
118
121
 
119
122
  let point = {} as IPointData, rotateP: IRect, resizeP: IRect, resizeL: IRect
120
123
 
@@ -138,11 +141,11 @@ export class EditBox extends Group implements IEditBox {
138
141
 
139
142
  if (((i + 1) / 2) % 2) { // top, bottom
140
143
  resizeL.width = width
141
- if (resizeP.width > width - 30) resizeP.visible = false
144
+ if (hideOnSmall && resizeP.width * 2 > width) resizeP.visible = false
142
145
  } else {
143
146
  resizeL.height = height
144
147
  resizeP.rotation = 90
145
- if (resizeP.width > height - 30) resizeP.visible = false
148
+ if (hideOnSmall && resizeP.width * 2 > height) resizeP.visible = false
146
149
  }
147
150
  }
148
151
 
@@ -154,7 +157,7 @@ export class EditBox extends Group implements IEditBox {
154
157
 
155
158
  // rect
156
159
  if (rect.path) rect.path = null // line可能会变成path优先模式
157
- rect.set({ ...bounds, visible: true })
160
+ rect.set({ ...bounds, visible: multiple ? true : editBox })
158
161
 
159
162
  // buttons
160
163
  buttons.visible = showPoints && buttons.children.length > 0
@@ -211,7 +214,7 @@ export class EditBox extends Group implements IEditBox {
211
214
 
212
215
  public getPointStyle(userStyle?: IBoxInputData): IBoxInputData {
213
216
  const { stroke, strokeWidth, pointFill, pointSize, pointRadius } = this.editor.mergeConfig
214
- const defaultStyle = { fill: pointFill, stroke, strokeWidth, around: 'center', strokeAlign: 'center', width: pointSize, height: pointSize, cornerRadius: pointRadius, offsetX: 0, offsetY: 0 } as IBoxInputData
217
+ const defaultStyle = { fill: pointFill, stroke, strokeWidth, around: 'center', strokeAlign: 'center', width: pointSize, height: pointSize, cornerRadius: pointRadius, offsetX: 0, offsetY: 0, editConfig } as IBoxInputData
215
218
  return userStyle ? Object.assign(defaultStyle, userStyle) : defaultStyle
216
219
  }
217
220
 
@@ -236,33 +239,31 @@ export class EditBox extends Group implements IEditBox {
236
239
 
237
240
  protected onDragStart(e: DragEvent): void {
238
241
  this.dragging = true
239
- const { editor } = this
240
- if (e.current.name === 'rect') {
242
+ const point = this.dragPoint = e.current as IEditPoint
243
+ const { editor, dragStartData } = this, { element } = editor
244
+ if (point.name === 'rect') {
241
245
  this.moving = true
242
- editor.dragStartPoint = { x: editor.element.x, y: editor.element.y }
243
246
  editor.opacity = editor.mergeConfig.hideOnMove ? 0 : 1 // move
244
- } else if ((e.current as IEditPoint).pointType === 'resize') {
245
- editor.dragStartBounds = { ...editor.element.getLayoutBounds('box', 'local') }
246
- editor.resizeDirection = (e.current as IEditPoint).direction
247
247
  }
248
+ dragStartData.x = e.x
249
+ dragStartData.y = e.y
250
+ dragStartData.point = { x: element.x, y: element.y } // 用于移动
251
+ dragStartData.bounds = { ...element.getLayoutBounds('box', 'local') } // 用于resize
252
+ dragStartData.rotation = element.rotation // 用于旋转
248
253
  }
249
254
 
250
255
  protected onDragEnd(e: DragEvent): void {
251
256
  this.dragging = false
257
+ this.dragPoint = null
252
258
  this.moving = false
253
259
  if (e.current.name === 'rect') this.editor.opacity = 1 // move
254
- this.editor.resizeDirection = undefined
255
-
256
260
  }
257
261
 
258
262
  protected onDrag(e: DragEvent): void {
259
263
  const { editor } = this
260
- const point = this.enterPoint = e.current as IEditPoint
261
- if (point.pointType === 'rotate' || e.metaKey || e.ctrlKey || !editor.mergeConfig.resizeable) {
262
- if (editor.mergeConfig.rotateable) editor.onRotate(e)
263
- } else if (point.pointType === 'resize') {
264
- editor.onScale(e)
265
- }
264
+ const { pointType } = this.enterPoint = e.current as IEditPoint
265
+ if (pointType.includes('rotate') || e.metaKey || e.ctrlKey || !editor.mergeConfig.resizeable) editor.onRotate(e)
266
+ if (pointType.includes('resize')) editor.onScale(e)
266
267
  updateCursor(editor, e)
267
268
  }
268
269
 
@@ -54,9 +54,9 @@ export class EditSelect extends Group implements IEditSelect {
54
54
 
55
55
  protected onSelect(): void {
56
56
  if (this.running) {
57
- const { mergeConfig: config, list } = this.editor
58
- const { stroke, strokeWidth } = config
59
- this.targetStroker.setTarget(list, { stroke, strokeWidth: Math.max(1, strokeWidth / 2) })
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 || {}) })
60
60
  this.hoverStroker.target = null
61
61
  }
62
62
  }
@@ -54,7 +54,7 @@ export class Stroker extends UI implements IStroker {
54
54
  leaf = list[i]
55
55
  const { worldTransform, worldRenderBounds } = leaf
56
56
 
57
- if (!bounds || bounds.hit(worldRenderBounds, options.matrix)) {
57
+ if (worldRenderBounds.width && worldRenderBounds.height && (!bounds || bounds.hit(worldRenderBounds, options.matrix))) {
58
58
 
59
59
  const aScaleX = abs(worldTransform.scaleX), aScaleY = abs(worldTransform.scaleY)
60
60
 
@@ -21,7 +21,7 @@ export function updateCursor(editor: IEditor, e: IUIEvent): void {
21
21
  const { resizeCursor, rotateCursor, skewCursor, resizeable, rotateable, skewable } = editor.mergeConfig
22
22
  const { pointType } = point, { flippedX, flippedY } = editBox
23
23
 
24
- let showResize = pointType === 'resize'
24
+ let showResize = pointType.includes('resize')
25
25
  if (showResize && rotateable && (e.metaKey || e.ctrlKey || !resizeable)) showResize = false
26
26
  const showSkew = skewable && !showResize && point.name === 'resize-line'
27
27
 
@@ -1,6 +1,6 @@
1
1
  import { LeafList } from '@leafer-ui/draw'
2
2
 
3
- import { IEditor, IUI } from '@leafer-in/interface'
3
+ import { IEditor, ILeaf, IUI } from '@leafer-in/interface'
4
4
 
5
5
  import { simulate } from './simulate'
6
6
  import { updateMoveCursor } from './cursor'
@@ -10,7 +10,11 @@ import { EditorEvent } from '../event/EditorEvent'
10
10
  export function onTarget(editor: IEditor, oldValue: IUI | IUI[]): void {
11
11
  const { target } = editor
12
12
  if (target) {
13
- editor.leafList = target instanceof LeafList ? target : new LeafList(target instanceof Array ? target : target as IUI)
13
+ const { list } = editor.leafList = target instanceof LeafList ? target : new LeafList(target instanceof Array ? target : target as IUI)
14
+ if (!list.every(checkEditable)) { // 过滤不合格的元素
15
+ editor.target = list.filter(checkEditable) as IUI[]
16
+ return
17
+ }
14
18
  if (editor.multiple) simulate(editor) // 更新模拟元素
15
19
  } else {
16
20
  editor.simulateTarget.remove()
@@ -37,5 +41,9 @@ export function onTarget(editor: IEditor, oldValue: IUI | IUI[]): void {
37
41
 
38
42
  export function onHover(editor: IEditor, oldValue: IUI): void {
39
43
  editor.emitEvent(new EditorEvent(EditorEvent.HOVER, { editor, value: editor.hoverTarget, oldValue }))
44
+ }
45
+
40
46
 
47
+ function checkEditable(item: ILeaf): boolean {
48
+ return item.editable && !item.locked
41
49
  }
@@ -10,7 +10,10 @@ function toList(value: IUI | IUI[]): IUI[] {
10
10
 
11
11
  export class EditorEvent extends Event implements IEditorEvent {
12
12
 
13
+ static BEFORE_SELECT = 'editor.before_select'
13
14
  static SELECT = 'editor.select'
15
+
16
+ static BEFORE_HOVER = 'editor.before_hover'
14
17
  static HOVER = 'editor.hover'
15
18
 
16
19
  declare readonly target: IUI
@@ -7,11 +7,17 @@ import { } from '../tool/InnerEditor'
7
7
 
8
8
  export class EditorGroupEvent extends EditorEvent implements IEditorGroupEvent {
9
9
 
10
+
11
+ static BEFORE_GROUP = 'editor.before_group'
10
12
  static GROUP = 'editor.group'
13
+
11
14
  static BEFORE_UNGROUP = 'editor.before_ungroup'
12
15
  static UNGROUP = 'editor.ungroup'
13
16
 
17
+ static BEFORE_OPEN = 'editor.before_open_group'
14
18
  static OPEN = 'editor.open_group'
19
+
20
+ static BEFORE_CLOSE = 'editor.before_close_group'
15
21
  static CLOSE = 'editor.close_group'
16
22
 
17
23
  readonly editTarget: IGroup
@@ -5,6 +5,7 @@ import { EditorEvent } from './EditorEvent'
5
5
 
6
6
  export class EditorMoveEvent extends EditorEvent implements IEditorMoveEvent {
7
7
 
8
+ static BEFORE_MOVE = 'editor.before_move'
8
9
  static MOVE = 'editor.move'
9
10
 
10
11
  readonly moveX: number
@@ -5,6 +5,7 @@ import { EditorEvent } from './EditorEvent'
5
5
 
6
6
  export class EditorRotateEvent extends EditorEvent implements IEditorRotateEvent {
7
7
 
8
+ static BEFORE_ROTATE = 'editor.before_rotate'
8
9
  static ROTATE = 'editor.rotate'
9
10
 
10
11
  // rotateOf(origin, rotation)
@@ -8,6 +8,7 @@ import { EditorEvent } from './EditorEvent'
8
8
 
9
9
  export class EditorScaleEvent extends EditorEvent implements IEditorScaleEvent {
10
10
 
11
+ static BEFORE_SCALE = 'editor.before_scale'
11
12
  static SCALE = 'editor.scale'
12
13
 
13
14
  // scaleOf(origin, scaleX, scaleY, resize)
@@ -5,6 +5,7 @@ import { EditorEvent } from './EditorEvent'
5
5
 
6
6
  export class EditorSkewEvent extends EditorEvent implements IEditorSkewEvent {
7
7
 
8
+ static BEFORE_SKEW = 'editor.before_skew'
8
9
  static SKEW = 'editor.skew'
9
10
 
10
11
  // skewOf(origin, skewX, skewY)
@@ -13,7 +13,7 @@ export const EditDataHelper = {
13
13
  getScaleData(element: IUI, startBounds: ILayoutBoundsData, direction: Direction9, totalMove: IPointData, lockRatio: boolean | 'corner', around: IAround, flipable: boolean, scaleMode: boolean): IEditorScaleEvent {
14
14
  let align: IAlign, origin = {} as IPointData, scaleX: number = 1, scaleY: number = 1
15
15
 
16
- const { boxBounds, widthRange, heightRange, dragBounds } = element
16
+ const { boxBounds, widthRange, heightRange, dragBounds, worldBoxBounds } = element
17
17
  const { width, height } = startBounds
18
18
 
19
19
  if (around) {
@@ -34,12 +34,6 @@ export const EditDataHelper = {
34
34
  totalMove.x *= scaleMode ? originChangedScaleX : signX
35
35
  totalMove.y *= scaleMode ? originChangedScaleY : signY
36
36
 
37
-
38
- // 防止变为0
39
- if (Math.abs(totalMove.x) === width) totalMove.x += 0.1
40
- if (Math.abs(totalMove.y) === height) totalMove.y += 0.1
41
-
42
-
43
37
  const topScale = (-totalMove.y + height) / height
44
38
  const rightScale = (totalMove.x + width) / width
45
39
  const bottomScale = (totalMove.y + height) / height
@@ -142,6 +136,10 @@ export const EditDataHelper = {
142
136
  scaleY = within(nowHeight * scaleY, heightRange) / nowHeight
143
137
  }
144
138
 
139
+ // 防止小于1px
140
+ if (Math.abs(scaleX * worldBoxBounds.width) < 1) scaleX = (scaleX < 0 ? -1 : 1) / worldBoxBounds.width
141
+ if (Math.abs(scaleY * worldBoxBounds.height) < 1) scaleY = (scaleY < 0 ? -1 : 1) / worldBoxBounds.height
142
+
145
143
  return { origin, scaleX, scaleY, direction, lockRatio, around }
146
144
  },
147
145
 
package/src/index.ts CHANGED
@@ -26,7 +26,7 @@ export { EditSelectHelper } from './helper/EditSelectHelper'
26
26
 
27
27
 
28
28
  import { IEditor, IEditorConfig, IEditToolFunction, IEditorConfigFunction } from '@leafer-in/interface'
29
- import { Creator, UI, Group, Text, Box, dataType, defineKey, Plugin } from '@leafer-ui/draw'
29
+ import { Creator, UI, Group, Text, Box, dataType, Plugin } from '@leafer-ui/draw'
30
30
 
31
31
  import '@leafer-in/resize'
32
32
 
@@ -38,41 +38,15 @@ Plugin.add('editor', 'resize')
38
38
 
39
39
  Creator.editor = function (options?: IEditorConfig): IEditor { return new Editor(options) }
40
40
 
41
+ Box.addAttr('textBox', false, dataType)
41
42
 
42
- dataType(false)(Box.prototype, 'textBox')
43
+ UI.addAttr('editConfig', undefined, dataType)
44
+ UI.addAttr('editOuter', (ui: UI) => ui.__.__isLinePath ? 'LineEditTool' : 'EditTool', dataType)
43
45
 
46
+ UI.addAttr('editInner', 'PathEditor', dataType)
47
+ Group.addAttr('editInner', '', dataType) // 必须设为空
48
+ Text.addAttr('editInner', 'TextEditor', dataType)
44
49
 
45
- defineKey(UI.prototype, 'editOuter', {
46
- get(): string { return this.__.__isLinePath ? 'LineEditTool' : 'EditTool' }
47
- })
48
-
49
- defineKey(UI.prototype, 'editInner', {
50
- get(): string { return 'PathEditor' }
51
- })
52
-
53
- defineKey(Group.prototype, 'editInner', { // 必须设为空
54
- get(): string { return '' }
55
- })
56
-
57
- defineKey(Text.prototype, 'editInner', {
58
- get(): string { return 'TextEditor' }
59
- })
60
-
61
-
62
- UI.setEditConfig = function (config: IEditorConfig | IEditorConfigFunction): void {
63
- defineKey(this.prototype, 'editConfig', {
64
- get(): IEditorConfig { return typeof config === 'function' ? config(this) : config }
65
- })
66
- }
67
-
68
- UI.setEditOuter = function (toolName: string | IEditToolFunction): void {
69
- defineKey(this.prototype, 'editOuter', {
70
- get(): string { return typeof toolName === 'string' ? toolName : toolName(this) }
71
- })
72
- }
73
-
74
- UI.setEditInner = function (editorName: string | IEditToolFunction): void {
75
- defineKey(this.prototype, 'editInner', {
76
- get(): string { return typeof editorName === 'string' ? editorName : editorName(this) }
77
- })
78
- }
50
+ UI.setEditConfig = function (config: IEditorConfig | IEditorConfigFunction): void { this.changeAttr('editConfig', config) }
51
+ UI.setEditOuter = function (toolName: string | IEditToolFunction): void { this.changeAttr('editOuter', toolName) }
52
+ UI.setEditInner = function (editorName: string | IEditToolFunction): void { this.changeAttr('editInner', editorName) }