@leafer-in/editor 1.6.7 → 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.6.7",
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.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.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
@@ -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
@@ -58,9 +52,15 @@ export class Editor extends Group implements IEditor {
58
52
  public get multiple(): boolean { return this.list.length > 1 }
59
53
  public get single(): boolean { return this.list.length === 1 }
60
54
 
55
+ public get dragPoint(): IEditPoint { return this.editBox.dragPoint }
56
+
61
57
  public get dragging(): boolean { return this.editBox.dragging }
58
+ public get gesturing(): boolean { return this.editBox.gesturing } // 手势操作元素中
59
+
62
60
  public get moving(): boolean { return this.editBox.moving }
63
- 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 }
64
64
 
65
65
  // 组件
66
66
 
@@ -137,19 +137,24 @@ export class Editor extends Group implements IEditor {
137
137
  }
138
138
 
139
139
  public updateEditTool(): void {
140
- const tool = this.editTool
140
+ this.unloadEditTool()
141
+
142
+ if (this.editing) {
143
+ const name = this.element.editOuter || 'EditTool'
144
+ const tool = this.editTool = this.editToolList[name] = this.editToolList[name] || EditToolCreator.get(name, this)
145
+ this.editBox.load()
146
+ tool.load()
147
+ this.update()
148
+ }
149
+ }
150
+
151
+ public unloadEditTool(): void {
152
+ let tool = this.editTool
141
153
  if (tool) {
142
154
  this.editBox.unload()
143
155
  tool.unload()
144
156
  this.editTool = null
145
157
  }
146
-
147
- 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)
150
- this.editBox.load()
151
- this.editTool.load()
152
- }
153
158
  }
154
159
 
155
160
 
@@ -159,232 +164,41 @@ export class Editor extends Group implements IEditor {
159
164
  return this.mergeConfig.editSize
160
165
  }
161
166
 
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
-
192
- if (e instanceof ZoomEvent) {
193
-
194
- if (resizeable === 'zoom') e.stop(), this.scaleOf(element.getBoxPoint(e), e.scale, e.scale)
195
-
196
- } else {
197
-
198
- const { direction } = e.current as IEditPoint
199
-
200
- if (e.shiftKey || element.lockRatio) lockRatio = true
201
-
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
167
 
240
- rotation = MathHelper.float(MathHelper.getGapRotation(rotation, rotateGap, element.rotation), 2)
241
- if (!rotation) return
168
+ // TransformTool will rewrite -----
242
169
 
243
- this.rotateOf(origin, rotation)
244
- }
170
+ // operate
245
171
 
172
+ public onMove(_e: DragEvent | MoveEvent): void { }
246
173
 
247
- public onSkew(e: DragEvent): void {
248
- const { element } = this
249
- const { around } = this.mergeConfig
174
+ public onScale(_e: DragEvent | ZoomEvent): void { }
250
175
 
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
176
+ public onRotate(_e: DragEvent | RotateEvent): void { }
253
177
 
254
- this.skewOf(origin, skewX, skewY)
255
- }
178
+ public onSkew(_e: DragEvent): void { }
256
179
 
257
180
 
258
181
  // transform
259
182
 
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
263
-
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
- }
270
-
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 }
274
-
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
-
183
+ public move(_x: number | IPointData, _y = 0): void { }
299
184
 
300
- override scaleOf(origin: IPointData | IAlign, scaleX: number, scaleY = scaleX, _resize?: boolean): void {
301
- if (!this.checkTransform('resizeable')) return
185
+ public scaleWithDrag(_data: IEditorScaleEvent): void { }
302
186
 
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
- }
187
+ override scaleOf(_origin: IPointData | IAlign, scaleX: number, _scaleY = scaleX, _resize?: boolean): void { }
309
188
 
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 }
189
+ override flip(_axis: IAxis): void { }
313
190
 
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
- }
191
+ override rotateOf(_origin: IPointData | IAlign, _rotation: number): void { }
319
192
 
320
- override flip(axis: IAxis): void {
321
- if (!this.checkTransform('resizeable')) return
193
+ override skewOf(_origin: IPointData | IAlign, _skewX: number, _skewY = 0, _resize?: boolean): void { }
322
194
 
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 }
195
+ public checkTransform(_type: 'moveable' | 'resizeable' | 'rotateable' | 'skewable'): boolean { return undefined }
327
196
 
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
- }
197
+ protected getWorldOrigin(_origin: IPointData | IAlign): IPointData { return undefined }
333
198
 
334
- override rotateOf(origin: IPointData | IAlign, rotation: number): void {
335
- if (!this.checkTransform('rotateable')) return
199
+ protected getChangedTransform(_func: IFunction): IMatrix { return undefined }
336
200
 
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
- }
343
-
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 }
347
-
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
- }
353
-
354
- override skewOf(origin: IPointData | IAlign, skewX: number, skewY = 0, _resize?: boolean): void {
355
- if (!this.checkTransform('skewable')) return
356
-
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
- }
363
-
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
- }
201
+ // --------
388
202
 
389
203
 
390
204
  // group
@@ -451,15 +265,20 @@ export class Editor extends Group implements IEditor {
451
265
 
452
266
  // inner
453
267
 
454
- 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
+
455
273
  if (target && select) this.target = target
274
+
456
275
  if (this.single) {
457
276
  const editTarget = target || this.element
458
- const tag = editTarget.editInner
459
- if (tag && EditToolCreator.list[tag]) {
277
+ name || (name = editTarget.editInner)
278
+ if (name && EditToolCreator.list[name]) {
460
279
  this.editTool.unload()
461
280
  this.innerEditing = true
462
- this.innerEditor = this.editToolList[tag] || EditToolCreator.get(tag, this)
281
+ this.innerEditor = this.editToolList[name] = this.editToolList[name] || EditToolCreator.get(name, this)
463
282
  this.innerEditor.editTarget = editTarget
464
283
 
465
284
  this.emitInnerEvent(InnerEditorEvent.BEFORE_OPEN)
@@ -469,7 +288,7 @@ export class Editor extends Group implements IEditor {
469
288
  }
470
289
  }
471
290
 
472
- public closeInnerEditor(): void {
291
+ public closeInnerEditor(onlyInnerEditor?: boolean): void {
473
292
  if (this.innerEditing) {
474
293
  this.innerEditing = false
475
294
 
@@ -477,7 +296,7 @@ export class Editor extends Group implements IEditor {
477
296
  this.innerEditor.unload()
478
297
  this.emitInnerEvent(InnerEditorEvent.CLOSE)
479
298
 
480
- this.editTool.load()
299
+ if (!onlyInnerEditor) this.updateEditTool()
481
300
  this.innerEditor = null
482
301
  }
483
302
  }
@@ -525,28 +344,15 @@ export class Editor extends Group implements IEditor {
525
344
  if (this.targetChanged) this.update()
526
345
  }
527
346
 
528
- protected onKey(e: KeyEvent): void {
529
- updateCursor(this, e)
530
- }
531
347
 
532
348
  // event
533
349
 
534
350
  public listenTargetEvents(): void {
535
351
  if (!this.targetEventIds.length) {
536
- const { app, leafer, editBox, editMask } = this
352
+ const { app, leafer, editMask } = this
537
353
  this.targetEventIds = [
538
354
  leafer.on_(RenderEvent.START, this.onRenderStart, this),
539
-
540
- app.on_([
541
- [RenderEvent.CHILD_START, this.onAppRenderStart, this],
542
-
543
- [MoveEvent.BEFORE_MOVE, this.onMove, this, true],
544
- [ZoomEvent.BEFORE_ZOOM, this.onScale, this, true],
545
- [RotateEvent.BEFORE_ROTATE, this.onRotate, this, true],
546
-
547
- [[KeyEvent.HOLD, KeyEvent.UP], this.onKey, this],
548
- [KeyEvent.DOWN, editBox.onArrow, editBox]
549
- ])
355
+ app.on_(RenderEvent.CHILD_START, this.onAppRenderStart, this)
550
356
  ]
551
357
  if (editMask.visible) editMask.forceRender()
552
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 // 强制锁定比例