@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/dist/editor.cjs +334 -263
- package/dist/editor.esm.js +331 -260
- package/dist/editor.esm.min.js +1 -1
- package/dist/editor.esm.min.js.map +1 -1
- package/dist/editor.js +334 -263
- package/dist/editor.min.cjs +1 -1
- package/dist/editor.min.cjs.map +1 -1
- package/dist/editor.min.js +1 -1
- package/dist/editor.min.js.map +1 -1
- package/package.json +6 -6
- package/src/Editor.ts +27 -229
- package/src/display/EditBox.ts +102 -53
- package/src/display/EditMask.ts +4 -3
- package/src/editor/cursor.ts +9 -10
- package/src/editor/simulate.ts +2 -2
- package/src/editor/target.ts +6 -5
- package/src/event/EditorEvent.ts +1 -0
- package/src/helper/EditDataHelper.ts +13 -13
- package/src/index.ts +2 -0
- package/src/tool/EditTool.ts +1 -4
- package/src/tool/InnerEditor.ts +6 -4
- package/src/tool/TransformTool.ts +294 -0
- package/types/index.d.ts +58 -22
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leafer-in/editor",
|
|
3
|
-
"version": "1.
|
|
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.
|
|
38
|
-
"@leafer-ui/core": "^1.
|
|
39
|
-
"@leafer-in/resize": "^1.
|
|
40
|
-
"@leafer-ui/interface": "^1.
|
|
41
|
-
"@leafer-in/interface": "^1.
|
|
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,
|
|
3
|
-
import { DragEvent, RotateEvent,
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
158
|
+
// TransformTool will rewrite -----
|
|
193
159
|
|
|
194
|
-
|
|
160
|
+
// operate
|
|
195
161
|
|
|
196
|
-
|
|
162
|
+
public onMove(_e: DragEvent | MoveEvent): void { }
|
|
197
163
|
|
|
198
|
-
|
|
164
|
+
public onScale(_e: DragEvent | ZoomEvent): void { }
|
|
199
165
|
|
|
200
|
-
|
|
166
|
+
public onRotate(_e: DragEvent | RotateEvent): void { }
|
|
201
167
|
|
|
202
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
355
|
-
if (!this.checkTransform('skewable')) return
|
|
187
|
+
protected getWorldOrigin(_origin: IPointData | IAlign): IPointData { return undefined }
|
|
356
188
|
|
|
357
|
-
|
|
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
|
-
|
|
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,
|
|
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()
|
package/src/display/EditBox.ts
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
101
|
-
|
|
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 (
|
|
105
|
-
|
|
106
|
-
this.app.interaction.bottomList = [{ target: rect, proxy:
|
|
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(
|
|
111
|
-
const {
|
|
112
|
-
const {
|
|
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 = !
|
|
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(
|
|
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:
|
|
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(
|
|
195
|
+
if (buttons.visible) this.layoutButtons()
|
|
166
196
|
} else rect.set(bounds) // 需要更新大小
|
|
167
197
|
}
|
|
168
198
|
|
|
169
|
-
protected layoutCircle(
|
|
170
|
-
const { circleDirection, circleMargin, buttonsMargin, buttonsDirection, middlePoint } =
|
|
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(
|
|
205
|
+
protected layoutButtons(): void {
|
|
176
206
|
const { buttons } = this
|
|
177
|
-
const { buttonsDirection, buttonsFixed, buttonsMargin, middlePoint } =
|
|
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.
|
|
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.
|
|
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.
|
|
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, {
|
|
274
|
+
const { editor, dragStartData } = this, { target } = this
|
|
245
275
|
if (point.name === 'rect') {
|
|
246
276
|
this.moving = true
|
|
247
|
-
editor.opacity =
|
|
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:
|
|
252
|
-
dragStartData.bounds = { ...
|
|
253
|
-
dragStartData.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 {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
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 &&
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
311
|
-
|
|
312
|
-
if (
|
|
313
|
-
|
|
314
|
-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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,
|
|
391
|
+
[DragEvent.DRAG, this.onDrag, this],
|
|
352
392
|
[DragEvent.END, this.onDragEnd, this],
|
|
353
393
|
|
|
354
|
-
[PointerEvent.ENTER, () => updateMoveCursor(
|
|
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 {
|