@leafer-in/editor 1.0.0-rc.3 → 1.0.0-rc.30
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 +1937 -0
- package/dist/editor.esm.js +1822 -422
- package/dist/editor.esm.min.js +1 -1
- package/dist/editor.js +1848 -428
- package/dist/editor.min.cjs +1 -0
- package/dist/editor.min.js +1 -1
- package/package.json +12 -9
- package/src/Editor.ts +396 -145
- package/src/config.ts +38 -0
- package/src/decorator/data.ts +16 -0
- package/src/display/EditBox.ts +342 -0
- package/src/display/EditMask.ts +37 -0
- package/src/display/EditPoint.ts +9 -0
- package/src/display/EditSelect.ts +255 -0
- package/src/display/SelectArea.ts +30 -0
- package/src/display/Stroker.ts +92 -0
- package/src/editor/cursor.ts +45 -0
- package/src/editor/simulate.ts +14 -0
- package/src/editor/target.ts +39 -0
- package/src/event/EditorEvent.ts +33 -0
- package/src/event/EditorGroupEvent.ts +23 -0
- package/src/event/EditorMoveEvent.ts +17 -0
- package/src/event/EditorRotateEvent.ts +4 -10
- package/src/event/EditorScaleEvent.ts +28 -0
- package/src/event/EditorSkewEvent.ts +18 -0
- package/src/event/InnerEditorEvent.ts +23 -0
- package/src/helper/EditDataHelper.ts +183 -0
- package/src/helper/EditSelectHelper.ts +34 -0
- package/src/helper/EditorHelper.ts +73 -0
- package/src/index.ts +50 -3
- package/src/svg.ts +54 -0
- package/src/tool/EditTool.ts +99 -0
- package/src/tool/EditToolCreator.ts +32 -0
- package/src/tool/InnerEditor.ts +68 -0
- package/src/tool/LineEditTool.ts +135 -0
- package/types/index.d.ts +293 -45
- package/src/cursor.ts +0 -57
- package/src/event/EditorResizeEvent.ts +0 -34
- package/src/resize.ts +0 -87
- package/src/tool/LineTool.ts +0 -88
- package/src/tool/RectTool.ts +0 -139
package/src/Editor.ts
CHANGED
|
@@ -1,232 +1,483 @@
|
|
|
1
|
-
import { IGroupInputData,
|
|
2
|
-
import {
|
|
1
|
+
import { IGroupInputData, IUI, IEventListenerId, IPointData, ILeafList, IEditSize, IGroup, IObject, IAlign } from '@leafer-ui/interface'
|
|
2
|
+
import { Group, Rect, DataHelper, MathHelper, LeafList, Matrix, RenderEvent, LeafHelper } from '@leafer-ui/draw'
|
|
3
|
+
import { DragEvent, RotateEvent, KeyEvent, ZoomEvent } from '@leafer-ui/core'
|
|
3
4
|
|
|
4
|
-
import {
|
|
5
|
+
import { IEditBox, IEditPoint, IEditor, IEditorConfig, IEditTool, IEditorScaleEvent, IInnerEditor } from '@leafer-in/interface'
|
|
5
6
|
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
7
|
+
import { EditorMoveEvent } from './event/EditorMoveEvent'
|
|
8
|
+
import { EditorScaleEvent } from './event/EditorScaleEvent'
|
|
9
|
+
import { EditorRotateEvent } from './event/EditorRotateEvent'
|
|
10
|
+
import { EditorSkewEvent } from './event/EditorSkewEvent'
|
|
8
11
|
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
12
|
+
import { EditSelect } from './display/EditSelect'
|
|
13
|
+
import { EditBox } from './display/EditBox'
|
|
14
|
+
import { EditMask } from './display/EditMask'
|
|
11
15
|
|
|
12
|
-
import {
|
|
13
|
-
|
|
16
|
+
import { config } from './config'
|
|
17
|
+
|
|
18
|
+
import { onTarget, onHover } from './editor/target'
|
|
19
|
+
import { targetAttr } from './decorator/data'
|
|
20
|
+
import { EditorHelper } from './helper/EditorHelper'
|
|
21
|
+
import { EditDataHelper } from './helper/EditDataHelper'
|
|
22
|
+
import { simulate } from './editor/simulate'
|
|
23
|
+
import { updateCursor } from './editor/cursor'
|
|
24
|
+
import { EditToolCreator } from './tool/EditToolCreator'
|
|
25
|
+
import { InnerEditorEvent } from './event/InnerEditorEvent'
|
|
26
|
+
import { EditorGroupEvent } from './event/EditorGroupEvent'
|
|
14
27
|
|
|
15
28
|
|
|
16
29
|
export class Editor extends Group implements IEditor {
|
|
17
30
|
|
|
18
|
-
public config
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
pointRadius: 10,
|
|
24
|
-
rotateGap: 90,
|
|
25
|
-
hideOnMove: false,
|
|
26
|
-
moveCursor: 'move',
|
|
27
|
-
resizeType: 'auto',
|
|
28
|
-
resizeCursor: ['nwse-resize', 'ns-resize', 'nesw-resize', 'ew-resize', 'nwse-resize', 'ns-resize', 'nesw-resize', 'ew-resize'],
|
|
29
|
-
rotateCursor: ['ne-resize', 'e-resize', 'se-resize', 's-resize', 'sw-resize', 'w-resize', 'nw-resize', 'n-resize'],
|
|
30
|
-
resizeable: true,
|
|
31
|
-
rotateable: true
|
|
31
|
+
public config = config
|
|
32
|
+
|
|
33
|
+
public get mergeConfig(): IEditorConfig {
|
|
34
|
+
const { element, config } = this
|
|
35
|
+
return this.single && element.editConfig ? { ...config, ...element.editConfig } : config // 实时合并,后期可优化
|
|
32
36
|
}
|
|
33
37
|
|
|
34
|
-
|
|
35
|
-
public
|
|
36
|
-
public resizeLines: IUI[] = [] // top, right, bottom, left
|
|
38
|
+
@targetAttr(onHover)
|
|
39
|
+
public hoverTarget?: IUI
|
|
37
40
|
|
|
38
|
-
|
|
39
|
-
public
|
|
40
|
-
public circle: IUI = new Rect({ around: 'center', hitRadius: 10 }) // rotate point
|
|
41
|
+
@targetAttr(onTarget)
|
|
42
|
+
public target?: IUI | IUI[]
|
|
41
43
|
|
|
42
|
-
|
|
44
|
+
// 列表
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
public
|
|
46
|
-
public
|
|
47
|
-
this.__removeTargetEvents()
|
|
48
|
-
this.visible = !!value
|
|
46
|
+
public get list(): IUI[] { return this.leafList.list as IUI[] }
|
|
47
|
+
public leafList: ILeafList = new LeafList() // from target
|
|
48
|
+
public openedGroupList: ILeafList = new LeafList()
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
50
|
+
// 状态
|
|
51
|
+
|
|
52
|
+
public get editing(): boolean { return !!this.list.length }
|
|
53
|
+
public innerEditing: boolean
|
|
54
|
+
public get groupOpening(): boolean { return !!this.openedGroupList.length }
|
|
55
|
+
|
|
56
|
+
public get multiple(): boolean { return this.list.length > 1 }
|
|
57
|
+
public get single(): boolean { return this.list.length === 1 }
|
|
58
|
+
|
|
59
|
+
public get dragging(): boolean { return this.editBox.dragging }
|
|
60
|
+
|
|
61
|
+
// 组件
|
|
62
|
+
|
|
63
|
+
public get element() { return this.multiple ? this.simulateTarget : this.list[0] as IUI }
|
|
64
|
+
public simulateTarget: IUI = new Rect({ visible: false })
|
|
65
|
+
|
|
66
|
+
public editBox: IEditBox = new EditBox(this)
|
|
67
|
+
public get buttons() { return this.editBox.buttons }
|
|
68
|
+
|
|
69
|
+
public editTool?: IEditTool
|
|
70
|
+
|
|
71
|
+
public innerEditor?: IInnerEditor
|
|
72
|
+
public editToolList: IObject = {}
|
|
73
|
+
|
|
74
|
+
public selector: EditSelect = new EditSelect(this)
|
|
75
|
+
public editMask: EditMask = new EditMask(this)
|
|
76
|
+
|
|
77
|
+
public dragStartPoint: IPointData
|
|
53
78
|
|
|
54
|
-
public
|
|
79
|
+
public targetEventIds: IEventListenerId[] = []
|
|
55
80
|
|
|
56
|
-
protected __eventIds: IEventListenerId[] = []
|
|
57
|
-
protected __targetEventIds: IEventListenerId[] = []
|
|
58
81
|
|
|
59
82
|
constructor(userConfig?: IEditorConfig, data?: IGroupInputData) {
|
|
60
83
|
super(data)
|
|
61
84
|
if (userConfig) this.config = DataHelper.default(userConfig, this.config)
|
|
62
|
-
this.
|
|
85
|
+
this.addMany(this.editMask, this.selector, this.editBox)
|
|
63
86
|
}
|
|
64
87
|
|
|
65
|
-
|
|
66
|
-
let rotatePoint: IUI, resizeLine: IUI, resizePoint: IUI
|
|
67
|
-
const { resizePoints, rotatePoints, resizeLines } = this
|
|
88
|
+
// select
|
|
68
89
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
this.__listenPointEvents(rotatePoint, 'rotate', i)
|
|
73
|
-
|
|
74
|
-
if (i % 2) {
|
|
75
|
-
resizeLine = new Rect({ around: 'center', width: 10, height: 10, hitFill: "all" })
|
|
76
|
-
resizeLines.push(resizeLine)
|
|
77
|
-
this.__listenPointEvents(resizeLine, 'resize', i)
|
|
78
|
-
}
|
|
90
|
+
public select(target: IUI | IUI[]): void {
|
|
91
|
+
this.target = target
|
|
92
|
+
}
|
|
79
93
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
94
|
+
public cancel(): void {
|
|
95
|
+
this.target = null
|
|
96
|
+
}
|
|
84
97
|
|
|
85
|
-
|
|
86
|
-
this.addMany(...rotatePoints, this.targetRect, this.rect, this.circle, ...resizeLines, ...resizePoints)
|
|
98
|
+
// item
|
|
87
99
|
|
|
88
|
-
|
|
100
|
+
public hasItem(item: IUI): boolean {
|
|
101
|
+
return this.leafList.has(item)
|
|
89
102
|
}
|
|
90
103
|
|
|
104
|
+
public addItem(item: IUI): void {
|
|
105
|
+
if (!this.hasItem(item) && !item.locked) this.leafList.add(item), this.target = this.leafList.list as IUI[]
|
|
106
|
+
}
|
|
91
107
|
|
|
92
|
-
|
|
93
|
-
this.
|
|
94
|
-
this.waitLeafer(() => {
|
|
95
|
-
this.update()
|
|
96
|
-
this.updateMoveCursor()
|
|
97
|
-
this.__listenTargetEvents()
|
|
98
|
-
})
|
|
108
|
+
public removeItem(item: IUI): void {
|
|
109
|
+
if (this.hasItem(item)) this.leafList.remove(item), this.target = this.leafList.list as IUI[]
|
|
99
110
|
}
|
|
100
111
|
|
|
101
|
-
public
|
|
102
|
-
|
|
112
|
+
public shiftItem(item: IUI): void {
|
|
113
|
+
this.hasItem(item) ? this.removeItem(item) : this.addItem(item)
|
|
103
114
|
}
|
|
104
115
|
|
|
116
|
+
// update
|
|
117
|
+
|
|
105
118
|
public update(): void {
|
|
106
|
-
if (
|
|
107
|
-
|
|
119
|
+
if (this.editing) {
|
|
120
|
+
if (this.innerEditing) this.innerEditor.update()
|
|
121
|
+
this.editTool.update()
|
|
122
|
+
this.selector.update()
|
|
123
|
+
}
|
|
108
124
|
}
|
|
109
125
|
|
|
126
|
+
public updateEditBox(): void {
|
|
127
|
+
if (this.multiple) simulate(this)
|
|
128
|
+
this.update()
|
|
129
|
+
}
|
|
110
130
|
|
|
111
|
-
|
|
112
|
-
const
|
|
113
|
-
if (
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
this.
|
|
131
|
+
public updateEditTool(): void {
|
|
132
|
+
const tool = this.editTool
|
|
133
|
+
if (tool) {
|
|
134
|
+
this.editBox.unload()
|
|
135
|
+
tool.unload()
|
|
136
|
+
this.editTool = null
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (this.editing) {
|
|
140
|
+
const tag = this.single ? this.list[0].editOuter as string : 'EditTool'
|
|
141
|
+
this.editTool = this.editToolList[tag] = this.editToolList[tag] || EditToolCreator.get(tag, this)
|
|
142
|
+
this.editBox.load()
|
|
143
|
+
this.editTool.load()
|
|
117
144
|
}
|
|
118
145
|
}
|
|
119
146
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
147
|
+
|
|
148
|
+
// get
|
|
149
|
+
|
|
150
|
+
public getEditSize(_ui: IUI): IEditSize {
|
|
151
|
+
return this.mergeConfig.editSize
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// operate
|
|
155
|
+
|
|
156
|
+
public onMove(e: DragEvent): void {
|
|
157
|
+
const total = { x: e.totalX, y: e.totalY }
|
|
158
|
+
|
|
123
159
|
if (e.shiftKey) {
|
|
124
|
-
if (Math.abs(x) > Math.abs(y))
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
160
|
+
if (Math.abs(total.x) > Math.abs(total.y)) total.y = 0
|
|
161
|
+
else total.x = 0
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
this.move(DragEvent.getValidMove(this.element, this.dragStartPoint, total))
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
public onScale(e: DragEvent | ZoomEvent): void {
|
|
168
|
+
const { element } = this
|
|
169
|
+
|
|
170
|
+
if (e instanceof ZoomEvent) {
|
|
171
|
+
if (this.mergeConfig.resizeable === 'zoom') {
|
|
172
|
+
e.stop()
|
|
173
|
+
this.scaleOf(element.getInnerPoint(e), e.scale, e.scale)
|
|
128
174
|
}
|
|
129
175
|
} else {
|
|
130
|
-
|
|
131
|
-
|
|
176
|
+
|
|
177
|
+
const { direction } = e.current as IEditPoint
|
|
178
|
+
let { around, lockRatio } = this.mergeConfig
|
|
179
|
+
if (e.shiftKey || element.lockRatio) lockRatio = true
|
|
180
|
+
|
|
181
|
+
const data = EditDataHelper.getScaleData(element.boxBounds, direction, e.getInnerMove(element), lockRatio, EditDataHelper.getAround(around, e.altKey))
|
|
182
|
+
|
|
183
|
+
if (this.editTool.onScaleWithDrag) {
|
|
184
|
+
data.drag = e
|
|
185
|
+
this.scaleWithDrag(data)
|
|
186
|
+
} else {
|
|
187
|
+
this.scaleOf(data.origin, data.scaleX, data.scaleY)
|
|
188
|
+
}
|
|
189
|
+
|
|
132
190
|
}
|
|
191
|
+
|
|
133
192
|
}
|
|
134
193
|
|
|
135
|
-
|
|
136
|
-
const {
|
|
137
|
-
const {
|
|
138
|
-
|
|
139
|
-
const origin = { x: x + width / 2, y: y + height / 2 }
|
|
194
|
+
public onRotate(e: DragEvent | RotateEvent): void {
|
|
195
|
+
const { skewable, around, rotateGap } = this.mergeConfig
|
|
196
|
+
const { direction, name } = e.current as IEditPoint
|
|
197
|
+
if (skewable && name === 'resize-line') return this.onSkew(e as DragEvent)
|
|
140
198
|
|
|
141
|
-
|
|
199
|
+
const { element } = this
|
|
200
|
+
let origin: IPointData, rotation: number
|
|
142
201
|
|
|
143
202
|
if (e instanceof RotateEvent) {
|
|
144
|
-
|
|
203
|
+
if (this.mergeConfig.rotateable === 'rotate') {
|
|
204
|
+
e.stop()
|
|
205
|
+
rotation = e.rotation, origin = element.getInnerPoint(e)
|
|
206
|
+
} else return
|
|
145
207
|
} else {
|
|
146
|
-
const
|
|
147
|
-
const
|
|
148
|
-
rotation =
|
|
208
|
+
const last = { x: e.x - e.moveX, y: e.y - e.moveY }
|
|
209
|
+
const data = EditDataHelper.getRotateData(element.boxBounds, direction, e.getInner(element), element.getInnerPoint(last), e.shiftKey ? null : (around || 'center'))
|
|
210
|
+
rotation = data.rotation
|
|
211
|
+
origin = data.origin
|
|
149
212
|
}
|
|
150
213
|
|
|
151
|
-
rotation = MathHelper.getGapRotation(
|
|
214
|
+
rotation = MathHelper.getGapRotation(rotation, rotateGap, element.rotation)
|
|
215
|
+
if (!rotation) return
|
|
216
|
+
|
|
217
|
+
if (element.scaleX * element.scaleY < 0) rotation = -rotation // flippedOne
|
|
218
|
+
|
|
219
|
+
this.rotateOf(origin, MathHelper.float(rotation, 2))
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
public onSkew(e: DragEvent): void {
|
|
224
|
+
const { element } = this
|
|
225
|
+
const { around } = this.mergeConfig
|
|
152
226
|
|
|
153
|
-
const
|
|
227
|
+
const { origin, skewX, skewY } = EditDataHelper.getSkewData(element.boxBounds, (e.current as IEditPoint).direction, e.getInnerMove(element), EditDataHelper.getAround(around, e.altKey))
|
|
228
|
+
if (!skewX && !skewY) return
|
|
154
229
|
|
|
155
|
-
this.
|
|
156
|
-
target.emitEvent(event)
|
|
230
|
+
this.skewOf(origin, skewX, skewY)
|
|
157
231
|
}
|
|
158
232
|
|
|
159
|
-
public onResize(e: DragEvent): void {
|
|
160
|
-
const { target } = this
|
|
161
|
-
const { __direction } = e.current.__
|
|
162
233
|
|
|
163
|
-
|
|
234
|
+
// transform
|
|
164
235
|
|
|
165
|
-
|
|
166
|
-
if (
|
|
236
|
+
public move(x: number | IPointData, y = 0): void {
|
|
237
|
+
if (!this.mergeConfig.moveable || this.element.locked) return
|
|
167
238
|
|
|
168
|
-
|
|
169
|
-
const
|
|
239
|
+
const { element } = this
|
|
240
|
+
const world = element.getWorldPointByLocal(typeof x === 'object' ? { ...x } : { x, y }, null, true)
|
|
241
|
+
const event = new EditorMoveEvent(EditorMoveEvent.MOVE, { target: element, editor: this, moveX: world.x, moveY: world.y })
|
|
170
242
|
|
|
171
|
-
|
|
243
|
+
this.editTool.onMove(event)
|
|
244
|
+
this.emitEvent(event)
|
|
172
245
|
|
|
173
|
-
this.
|
|
174
|
-
target.emitEvent(event)
|
|
246
|
+
if (this.multiple) element.move(x, y)
|
|
175
247
|
}
|
|
176
248
|
|
|
249
|
+
public scaleWithDrag(data: IEditorScaleEvent): void {
|
|
250
|
+
if (!this.mergeConfig.resizeable || this.element.locked) return
|
|
177
251
|
|
|
178
|
-
|
|
179
|
-
|
|
252
|
+
const { element } = this
|
|
253
|
+
const worldOrigin = element.getWorldPoint(data.origin)
|
|
254
|
+
const event = new EditorScaleEvent(EditorScaleEvent.SCALE, { ...data, target: element, editor: this, worldOrigin })
|
|
255
|
+
|
|
256
|
+
this.editTool.onScaleWithDrag(event)
|
|
257
|
+
this.emitEvent(event)
|
|
180
258
|
}
|
|
181
259
|
|
|
182
260
|
|
|
183
|
-
|
|
184
|
-
this.
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
261
|
+
public scaleOf(origin: IPointData | IAlign, scaleX: number, scaleY = scaleX, _resize?: boolean): void {
|
|
262
|
+
if (!this.mergeConfig.resizeable || this.element.locked) return
|
|
263
|
+
|
|
264
|
+
const { element } = this
|
|
265
|
+
const worldOrigin = element.getWorldPoint(LeafHelper.getInnerOrigin(element, origin))
|
|
266
|
+
|
|
267
|
+
let transform: Matrix
|
|
268
|
+
|
|
269
|
+
if (this.multiple) {
|
|
270
|
+
const oldMatrix = new Matrix(element.worldTransform)
|
|
271
|
+
element.scaleOf(origin, scaleX, scaleY)
|
|
272
|
+
transform = new Matrix(element.worldTransform).divide(oldMatrix) // world change transform
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const event = new EditorScaleEvent(EditorScaleEvent.SCALE, { target: element, editor: this, worldOrigin, scaleX, scaleY, transform })
|
|
276
|
+
|
|
277
|
+
this.editTool.onScale(event)
|
|
278
|
+
this.emitEvent(event)
|
|
190
279
|
}
|
|
191
280
|
|
|
192
|
-
|
|
193
|
-
this.
|
|
194
|
-
|
|
281
|
+
public rotateOf(origin: IPointData | IAlign, rotation: number): void {
|
|
282
|
+
if (!this.mergeConfig.rotateable || this.element.locked) return
|
|
283
|
+
|
|
284
|
+
const { element } = this
|
|
285
|
+
const worldOrigin = element.getWorldPoint(LeafHelper.getInnerOrigin(element, origin))
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
let transform: Matrix
|
|
289
|
+
|
|
290
|
+
if (this.multiple) {
|
|
291
|
+
const oldMatrix = new Matrix(element.worldTransform)
|
|
292
|
+
element.rotateOf(origin, rotation)
|
|
293
|
+
transform = new Matrix(element.worldTransform).divide(oldMatrix) // world change transform
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const event = new EditorRotateEvent(EditorRotateEvent.ROTATE, { target: element, editor: this, worldOrigin, rotation, transform })
|
|
297
|
+
|
|
298
|
+
this.editTool.onRotate(event)
|
|
299
|
+
this.emitEvent(event)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
public skewOf(origin: IPointData | IAlign, skewX: number, skewY = 0, _resize?: boolean): void {
|
|
303
|
+
if (!this.mergeConfig.skewable || this.element.locked) return
|
|
304
|
+
|
|
305
|
+
const { element } = this
|
|
306
|
+
const worldOrigin = element.getWorldPoint(LeafHelper.getInnerOrigin(element, origin))
|
|
307
|
+
|
|
308
|
+
let transform: Matrix
|
|
309
|
+
|
|
310
|
+
if (this.multiple) {
|
|
311
|
+
const oldMatrix = new Matrix(element.worldTransform)
|
|
312
|
+
element.skewOf(origin, skewX, skewY)
|
|
313
|
+
transform = new Matrix(element.worldTransform).divide(oldMatrix) // world change transform
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const event = new EditorSkewEvent(EditorSkewEvent.SKEW, {
|
|
317
|
+
target: element, editor: this, skewX, skewY, transform, worldOrigin
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
this.editTool.onSkew(event)
|
|
321
|
+
this.emitEvent(event)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// group
|
|
325
|
+
|
|
326
|
+
public group(userGroup?: IGroup | IGroupInputData): IGroup {
|
|
327
|
+
if (this.multiple) {
|
|
328
|
+
this.target = EditorHelper.group(this.list, this.element, userGroup)
|
|
329
|
+
this.emitGroupEvent(EditorGroupEvent.GROUP, this.target as IGroup)
|
|
330
|
+
}
|
|
331
|
+
return this.target as IGroup
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
public ungroup(): IUI[] {
|
|
335
|
+
const { list } = this
|
|
336
|
+
if (list.length) {
|
|
337
|
+
list.forEach(item => item.isBranch && this.emitGroupEvent(EditorGroupEvent.BEFORE_UNGROUP, item as IGroup))
|
|
338
|
+
this.target = EditorHelper.ungroup(list)
|
|
339
|
+
list.forEach(item => item.isBranch && this.emitGroupEvent(EditorGroupEvent.UNGROUP, item as IGroup))
|
|
340
|
+
}
|
|
341
|
+
return this.list
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
public openGroup(group: IGroup): void {
|
|
345
|
+
this.openedGroupList.add(group)
|
|
346
|
+
group.hitChildren = true
|
|
347
|
+
this.emitGroupEvent(EditorGroupEvent.OPEN, group)
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
public closeGroup(group: IGroup): void {
|
|
351
|
+
this.openedGroupList.remove(group)
|
|
352
|
+
group.hitChildren = false
|
|
353
|
+
this.emitGroupEvent(EditorGroupEvent.CLOSE, group)
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
public checkOpenedGroups(): void {
|
|
357
|
+
const opened = this.openedGroupList
|
|
358
|
+
if (opened.length) {
|
|
359
|
+
let { list } = opened
|
|
360
|
+
if (this.editing) list = [], opened.forEach(item => this.list.every(leaf => !LeafHelper.hasParent(leaf, item)) && list.push(item))
|
|
361
|
+
list.forEach(item => this.closeGroup(item as IGroup))
|
|
362
|
+
}
|
|
363
|
+
if (this.editing && !this.selector.dragging) this.checkDeepSelect()
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
public checkDeepSelect(): void {
|
|
367
|
+
let parent: IGroup, { list } = this
|
|
368
|
+
for (let i = 0; i < list.length; i++) {
|
|
369
|
+
parent = list[i].parent
|
|
370
|
+
while (parent && !parent.hitChildren) {
|
|
371
|
+
this.openGroup(parent)
|
|
372
|
+
parent = parent.parent
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
public emitGroupEvent(type: string, group: IGroup): void {
|
|
378
|
+
const event = new EditorGroupEvent(type, { editTarget: group })
|
|
379
|
+
this.emitEvent(event)
|
|
380
|
+
group.emitEvent(event)
|
|
195
381
|
}
|
|
196
382
|
|
|
383
|
+
// inner
|
|
384
|
+
|
|
385
|
+
public openInnerEditor(target?: IUI): void {
|
|
386
|
+
if (target) this.target = target
|
|
387
|
+
if (this.single) {
|
|
388
|
+
const editTarget = this.element
|
|
389
|
+
const tag = editTarget.editInner
|
|
390
|
+
if (tag && EditToolCreator.list[tag]) {
|
|
391
|
+
this.editTool.unload()
|
|
392
|
+
this.innerEditing = true
|
|
393
|
+
this.innerEditor = this.editToolList[tag] || EditToolCreator.get(tag, this)
|
|
394
|
+
this.innerEditor.editTarget = editTarget
|
|
395
|
+
|
|
396
|
+
this.emitInnerEvent(InnerEditorEvent.BEFORE_OPEN)
|
|
397
|
+
this.innerEditor.load()
|
|
398
|
+
this.emitInnerEvent(InnerEditorEvent.OPEN)
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
public closeInnerEditor(): void {
|
|
404
|
+
if (this.innerEditing) {
|
|
405
|
+
this.innerEditing = false
|
|
406
|
+
|
|
407
|
+
this.emitInnerEvent(InnerEditorEvent.BEFORE_CLOSE)
|
|
408
|
+
this.innerEditor.unload()
|
|
409
|
+
this.emitInnerEvent(InnerEditorEvent.CLOSE)
|
|
410
|
+
|
|
411
|
+
this.editTool.load()
|
|
412
|
+
this.innerEditor = null
|
|
413
|
+
}
|
|
414
|
+
}
|
|
197
415
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
416
|
+
public emitInnerEvent(type: string): void {
|
|
417
|
+
const { innerEditor } = this
|
|
418
|
+
const { editTarget } = innerEditor
|
|
419
|
+
const event = new InnerEditorEvent(type, { editTarget, innerEditor })
|
|
420
|
+
this.emitEvent(event)
|
|
421
|
+
editTarget.emitEvent(event)
|
|
204
422
|
}
|
|
205
423
|
|
|
424
|
+
// lock
|
|
206
425
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
426
|
+
public lock(): void {
|
|
427
|
+
this.list.forEach(leaf => leaf.locked = true)
|
|
428
|
+
this.update()
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
public unlock(): void {
|
|
432
|
+
this.list.forEach(leaf => leaf.locked = false)
|
|
433
|
+
this.update()
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// level
|
|
437
|
+
|
|
438
|
+
public toTop(): void {
|
|
439
|
+
if (this.list.length) {
|
|
440
|
+
EditorHelper.toTop(this.list)
|
|
441
|
+
this.leafList.update()
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
public toBottom(): void {
|
|
446
|
+
if (this.list.length) {
|
|
447
|
+
EditorHelper.toBottom(this.list)
|
|
448
|
+
this.leafList.update()
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// event
|
|
453
|
+
|
|
454
|
+
public listenTargetEvents(): void {
|
|
455
|
+
if (!this.targetEventIds.length) {
|
|
456
|
+
const { leafer } = this.list[0]
|
|
457
|
+
this.targetEventIds = [
|
|
211
458
|
leafer.on_(RenderEvent.START, this.update, this),
|
|
212
|
-
leafer.on_([KeyEvent.HOLD, KeyEvent.UP], (e) => { updateCursor(this, e) })
|
|
459
|
+
leafer.on_([KeyEvent.HOLD, KeyEvent.UP], (e: KeyEvent) => { updateCursor(this, e) }),
|
|
460
|
+
leafer.on_(KeyEvent.DOWN, this.editBox.onArrow, this.editBox)
|
|
213
461
|
]
|
|
214
462
|
}
|
|
215
463
|
}
|
|
216
464
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
465
|
+
public removeTargetEvents(): void {
|
|
466
|
+
const { targetEventIds } = this
|
|
467
|
+
if (targetEventIds.length) {
|
|
468
|
+
this.off_(targetEventIds)
|
|
469
|
+
targetEventIds.length = 0
|
|
222
470
|
}
|
|
223
471
|
}
|
|
224
472
|
|
|
225
|
-
|
|
226
473
|
public destroy(): void {
|
|
227
|
-
this.
|
|
228
|
-
|
|
229
|
-
|
|
474
|
+
if (!this.destroyed) {
|
|
475
|
+
this.simulateTarget.destroy()
|
|
476
|
+
Object.values(this.editToolList).forEach(item => item.destroy())
|
|
477
|
+
this.editToolList = {}
|
|
478
|
+
this.target = this.hoverTarget = this.simulateTarget = this.editTool = this.innerEditor = null
|
|
479
|
+
super.destroy()
|
|
480
|
+
}
|
|
230
481
|
}
|
|
231
482
|
|
|
232
483
|
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { IEditorConfig } from '@leafer-in/interface'
|
|
2
|
+
import { resizeSVG, rotateSVG, skewSVG } from './svg'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export const config: IEditorConfig = {
|
|
6
|
+
editSize: 'size',
|
|
7
|
+
keyEvent: true,
|
|
8
|
+
|
|
9
|
+
stroke: '#836DFF',
|
|
10
|
+
strokeWidth: 2,
|
|
11
|
+
|
|
12
|
+
pointFill: '#FFFFFF',
|
|
13
|
+
pointSize: 10,
|
|
14
|
+
pointRadius: 16,
|
|
15
|
+
|
|
16
|
+
rotateGap: 45,
|
|
17
|
+
|
|
18
|
+
buttonsDirection: 'bottom',
|
|
19
|
+
buttonsMargin: 12,
|
|
20
|
+
|
|
21
|
+
hideOnSmall: true,
|
|
22
|
+
|
|
23
|
+
moveCursor: 'move',
|
|
24
|
+
resizeCursor: { url: resizeSVG, x: 12, y: 12 },
|
|
25
|
+
rotateCursor: { url: rotateSVG, x: 12, y: 12 },
|
|
26
|
+
skewCursor: { url: skewSVG, x: 12, y: 12 },
|
|
27
|
+
|
|
28
|
+
selector: true,
|
|
29
|
+
hover: true,
|
|
30
|
+
select: 'press',
|
|
31
|
+
openInner: 'double',
|
|
32
|
+
boxSelect: true,
|
|
33
|
+
|
|
34
|
+
moveable: true,
|
|
35
|
+
resizeable: true,
|
|
36
|
+
rotateable: true,
|
|
37
|
+
skewable: true
|
|
38
|
+
}
|