@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/dist/editor.cjs +452 -328
- package/dist/editor.esm.js +449 -325
- package/dist/editor.esm.min.js +1 -1
- package/dist/editor.esm.min.js.map +1 -1
- package/dist/editor.js +452 -328
- 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 +54 -248
- package/src/decorator/data.ts +4 -2
- package/src/display/EditBox.ts +184 -77
- package/src/display/EditMask.ts +4 -3
- package/src/display/EditSelect.ts +4 -4
- package/src/display/Stroker.ts +4 -3
- package/src/editor/cursor.ts +12 -10
- package/src/editor/simulate.ts +2 -2
- package/src/editor/target.ts +7 -5
- package/src/event/EditorEvent.ts +1 -0
- package/src/helper/EditDataHelper.ts +23 -19
- package/src/index.ts +3 -1
- package/src/tool/EditTool.ts +1 -4
- package/src/tool/InnerEditor.ts +6 -4
- package/src/tool/TransformTool.ts +282 -0
- package/types/index.d.ts +96 -46
package/src/display/EditBox.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { IRect, IEventListenerId, IBoundsData, IPointData, IKeyEvent, IGroup, IBox, IBoxInputData, IAlign, IUI, IEditorConfig, IEditorDragStartData, IEventParams } from '@leafer-ui/interface'
|
|
2
|
-
import { Group, Box, Text, AroundHelper, Direction9, ResizeEvent } from '@leafer-ui/draw'
|
|
3
|
-
import { DragEvent, PointerEvent } from '@leafer-ui/core'
|
|
1
|
+
import { IRect, IEventListenerId, IBoundsData, IPointData, IKeyEvent, IGroup, IBox, IBoxInputData, IAlign, IUI, IEditorConfig, IEditorDragStartData, IEventParams, ITransformTool } from '@leafer-ui/interface'
|
|
2
|
+
import { Group, Box, Text, AroundHelper, Direction9, ResizeEvent, BoundsHelper } from '@leafer-ui/draw'
|
|
3
|
+
import { DragEvent, PointerEvent, KeyEvent, RotateEvent, ZoomEvent, MoveEvent } from '@leafer-ui/core'
|
|
4
4
|
|
|
5
5
|
import { IEditBox, IEditor, IEditPoint, IEditPointType } from '@leafer-in/interface'
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import { EditorEvent } from '../event/EditorEvent'
|
|
7
|
+
import { updatePointCursor, updateMoveCursor } from '../editor/cursor'
|
|
9
8
|
import { EditPoint } from './EditPoint'
|
|
10
9
|
import { EditDataHelper } from '../helper/EditDataHelper'
|
|
11
10
|
|
|
@@ -15,8 +14,14 @@ const fourDirection = ['top', 'right', 'bottom', 'left'], editConfig: IEditorCon
|
|
|
15
14
|
export class EditBox extends Group implements IEditBox {
|
|
16
15
|
|
|
17
16
|
public editor: IEditor
|
|
17
|
+
|
|
18
18
|
public dragging: boolean
|
|
19
|
+
public gesturing: boolean
|
|
20
|
+
|
|
19
21
|
public moving: boolean
|
|
22
|
+
public resizing: boolean
|
|
23
|
+
public rotating: boolean
|
|
24
|
+
public skewing: boolean
|
|
20
25
|
|
|
21
26
|
public view: IGroup = new Group() // 放置默认编辑工具控制点
|
|
22
27
|
|
|
@@ -33,12 +38,37 @@ export class EditBox extends Group implements IEditBox {
|
|
|
33
38
|
|
|
34
39
|
public dragStartData = {} as IEditorDragStartData
|
|
35
40
|
|
|
41
|
+
public config: IEditorConfig
|
|
42
|
+
public mergedConfig: IEditorConfig
|
|
43
|
+
|
|
44
|
+
public get mergeConfig(): IEditorConfig {
|
|
45
|
+
const { config } = this, { mergeConfig, editBox } = this.editor
|
|
46
|
+
return this.mergedConfig = config && (editBox !== this) ? { ...mergeConfig, ...config } : mergeConfig // 可能会出现多个editBox的情况
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
protected _target: IUI
|
|
50
|
+
public get target(): IUI { return this._target || this.editor.element } // 操作的元素,默认为editor.element
|
|
51
|
+
public set target(target: IUI) { this._target = target }
|
|
52
|
+
|
|
53
|
+
public get single(): boolean { return !!this._target || this.editor.single }
|
|
54
|
+
|
|
55
|
+
protected _transformTool: ITransformTool
|
|
56
|
+
public get transformTool(): ITransformTool { return this._transformTool || this.editor }
|
|
57
|
+
public set transformTool(tool: ITransformTool) { this._transformTool = tool }
|
|
58
|
+
|
|
36
59
|
// fliped
|
|
37
60
|
public get flipped(): boolean { return this.flippedX || this.flippedY }
|
|
38
61
|
public get flippedX(): boolean { return this.scaleX < 0 }
|
|
39
62
|
public get flippedY(): boolean { return this.scaleY < 0 }
|
|
40
63
|
public get flippedOne(): boolean { return this.scaleX * this.scaleY < 0 }
|
|
41
64
|
|
|
65
|
+
public get canUse(): boolean { return (this.visible && this.view.visible) as boolean } // 编辑框是否处于激活状态
|
|
66
|
+
public get canGesture(): boolean { // 是否支持手势
|
|
67
|
+
if (!this.canUse) return false
|
|
68
|
+
const { moveable, resizeable, rotateable } = this.mergeConfig
|
|
69
|
+
return typeof moveable === 'string' || typeof resizeable === 'string' || typeof rotateable === 'string'
|
|
70
|
+
}
|
|
71
|
+
|
|
42
72
|
protected __eventIds: IEventListenerId[] = []
|
|
43
73
|
|
|
44
74
|
constructor(editor: IEditor) {
|
|
@@ -76,9 +106,9 @@ export class EditBox extends Group implements IEditBox {
|
|
|
76
106
|
this.add(view)
|
|
77
107
|
}
|
|
78
108
|
|
|
109
|
+
|
|
79
110
|
public load(): void {
|
|
80
|
-
const {
|
|
81
|
-
const { rect, circle, resizePoints } = this
|
|
111
|
+
const { target, mergeConfig, single, rect, circle, resizePoints } = this
|
|
82
112
|
const { stroke, strokeWidth } = mergeConfig
|
|
83
113
|
|
|
84
114
|
const pointsStyle = this.getPointsStyle()
|
|
@@ -89,7 +119,7 @@ export class EditBox extends Group implements IEditBox {
|
|
|
89
119
|
for (let i = 0; i < 8; i++) {
|
|
90
120
|
resizeP = resizePoints[i]
|
|
91
121
|
resizeP.set(this.getPointStyle((i % 2) ? middlePointsStyle[((i - 1) / 2) % middlePointsStyle.length] : pointsStyle[(i / 2) % pointsStyle.length]))
|
|
92
|
-
|
|
122
|
+
resizeP.rotation = ((i - (i % 2 ? 1 : 0)) / 2) * 90
|
|
93
123
|
}
|
|
94
124
|
|
|
95
125
|
// rotate
|
|
@@ -97,24 +127,44 @@ export class EditBox extends Group implements IEditBox {
|
|
|
97
127
|
|
|
98
128
|
// rect
|
|
99
129
|
rect.set({ stroke, strokeWidth, editConfig, ...(mergeConfig.rect || {}) })
|
|
100
|
-
rect.hittable = !single
|
|
101
|
-
rect.syncEventer = single && this.editor // 单选下 rect 的事件不会冒泡,需要手动传递给editor
|
|
102
130
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
131
|
+
const syncEventer = single && this.transformTool.editTool
|
|
132
|
+
|
|
133
|
+
// 编辑框作为底部虚拟元素, 在 unload() 中重置
|
|
134
|
+
rect.hittable = !syncEventer
|
|
135
|
+
rect.syncEventer = syncEventer && this.editor // 单选下 rect 的事件不会冒泡,需要手动传递给editor
|
|
136
|
+
|
|
137
|
+
if (syncEventer) {
|
|
138
|
+
target.syncEventer = rect // 在 target 属性装饰中重置
|
|
139
|
+
this.app.interaction.bottomList = [{ target: rect, proxy: target }]
|
|
107
140
|
}
|
|
141
|
+
|
|
142
|
+
updateMoveCursor(this)
|
|
108
143
|
}
|
|
109
144
|
|
|
110
|
-
public update(
|
|
111
|
-
const {
|
|
112
|
-
const {
|
|
113
|
-
|
|
145
|
+
public update(): void {
|
|
146
|
+
const { editor } = this
|
|
147
|
+
const { x, y, scaleX, scaleY, rotation, skewX, skewY, width, height } = this.target.getLayoutBounds('box', editor, true)
|
|
148
|
+
this.set({ x, y, scaleX, scaleY, rotation, skewX, skewY })
|
|
149
|
+
this.updateBounds({ x: 0, y: 0, width, height })
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
public unload(): void {
|
|
153
|
+
this.visible = false
|
|
154
|
+
if (this.app) this.rect.syncEventer = this.app.interaction.bottomList = null
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
public updateBounds(bounds: IBoundsData): void {
|
|
159
|
+
const { editMask } = this.editor
|
|
160
|
+
const { mergeConfig, single, rect, circle, buttons, resizePoints, rotatePoints, resizeLines } = this
|
|
161
|
+
const { middlePoint, resizeable, rotateable, hideOnSmall, editBox, mask, spread } = mergeConfig
|
|
114
162
|
|
|
115
|
-
this.visible = !
|
|
163
|
+
this.visible = !this.target.locked
|
|
116
164
|
editMask.visible = mask ? true : 0
|
|
117
165
|
|
|
166
|
+
if (spread) BoundsHelper.spread(bounds, spread)
|
|
167
|
+
|
|
118
168
|
if (this.view.worldOpacity) {
|
|
119
169
|
const { width, height } = bounds
|
|
120
170
|
const smallSize = typeof hideOnSmall === 'number' ? hideOnSmall : 10
|
|
@@ -145,7 +195,6 @@ export class EditBox extends Group implements IEditBox {
|
|
|
145
195
|
if (hideOnSmall && resizeP.width * 2 > width) resizeP.visible = false
|
|
146
196
|
} else {
|
|
147
197
|
resizeL.height = height
|
|
148
|
-
resizeP.rotation = 90
|
|
149
198
|
if (hideOnSmall && resizeP.width * 2 > height) resizeP.visible = false
|
|
150
199
|
}
|
|
151
200
|
}
|
|
@@ -154,27 +203,27 @@ export class EditBox extends Group implements IEditBox {
|
|
|
154
203
|
|
|
155
204
|
// rotate
|
|
156
205
|
circle.visible = showPoints && rotateable && !!(mergeConfig.circle || mergeConfig.rotatePoint)
|
|
157
|
-
if (circle.visible) this.layoutCircle(
|
|
206
|
+
if (circle.visible) this.layoutCircle()
|
|
158
207
|
|
|
159
208
|
// rect
|
|
160
209
|
if (rect.path) rect.path = null // line可能会变成path优先模式
|
|
161
|
-
rect.set({ ...bounds, visible:
|
|
210
|
+
rect.set({ ...bounds, visible: single ? editBox : true })
|
|
162
211
|
|
|
163
212
|
// buttons
|
|
164
213
|
buttons.visible = showPoints && buttons.children.length > 0 || 0
|
|
165
|
-
if (buttons.visible) this.layoutButtons(
|
|
214
|
+
if (buttons.visible) this.layoutButtons()
|
|
166
215
|
} else rect.set(bounds) // 需要更新大小
|
|
167
216
|
}
|
|
168
217
|
|
|
169
|
-
protected layoutCircle(
|
|
170
|
-
const { circleDirection, circleMargin, buttonsMargin, buttonsDirection, middlePoint } =
|
|
218
|
+
protected layoutCircle(): void {
|
|
219
|
+
const { circleDirection, circleMargin, buttonsMargin, buttonsDirection, middlePoint } = this.mergedConfig
|
|
171
220
|
const direction = fourDirection.indexOf(circleDirection || ((this.buttons.children.length && buttonsDirection === 'bottom') ? 'top' : 'bottom'))
|
|
172
221
|
this.setButtonPosition(this.circle, direction, circleMargin || buttonsMargin, !!middlePoint)
|
|
173
222
|
}
|
|
174
223
|
|
|
175
|
-
protected layoutButtons(
|
|
224
|
+
protected layoutButtons(): void {
|
|
176
225
|
const { buttons } = this
|
|
177
|
-
const { buttonsDirection, buttonsFixed, buttonsMargin, middlePoint } =
|
|
226
|
+
const { buttonsDirection, buttonsFixed, buttonsMargin, middlePoint } = this.mergedConfig
|
|
178
227
|
|
|
179
228
|
const { flippedX, flippedY } = this
|
|
180
229
|
let index = fourDirection.indexOf(buttonsDirection)
|
|
@@ -208,75 +257,119 @@ export class EditBox extends Group implements IEditBox {
|
|
|
208
257
|
}
|
|
209
258
|
|
|
210
259
|
|
|
211
|
-
public unload(): void {
|
|
212
|
-
this.visible = false
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
|
|
216
260
|
public getPointStyle(userStyle?: IBoxInputData): IBoxInputData {
|
|
217
|
-
const { stroke, strokeWidth, pointFill, pointSize, pointRadius } = this.
|
|
261
|
+
const { stroke, strokeWidth, pointFill, pointSize, pointRadius } = this.mergedConfig
|
|
218
262
|
const defaultStyle = { fill: pointFill, stroke, strokeWidth, around: 'center', strokeAlign: 'center', width: pointSize, height: pointSize, cornerRadius: pointRadius, offsetX: 0, offsetY: 0, editConfig } as IBoxInputData
|
|
219
263
|
return userStyle ? Object.assign(defaultStyle, userStyle) : defaultStyle
|
|
220
264
|
}
|
|
221
265
|
|
|
222
266
|
public getPointsStyle(): IBoxInputData[] {
|
|
223
|
-
const { point } = this.
|
|
267
|
+
const { point } = this.mergedConfig
|
|
224
268
|
return point instanceof Array ? point : [point]
|
|
225
269
|
}
|
|
226
270
|
|
|
227
271
|
public getMiddlePointsStyle(): IBoxInputData[] {
|
|
228
|
-
const { middlePoint } = this.
|
|
272
|
+
const { middlePoint } = this.mergedConfig
|
|
229
273
|
return middlePoint instanceof Array ? middlePoint : (middlePoint ? [middlePoint] : this.getPointsStyle())
|
|
230
274
|
}
|
|
231
275
|
|
|
232
|
-
protected onSelect(e: EditorEvent): void {
|
|
233
|
-
if (e.oldList.length === 1) {
|
|
234
|
-
e.oldList[0].syncEventer = null
|
|
235
|
-
if (this.app) this.app.interaction.bottomList = null
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
276
|
|
|
239
277
|
// drag
|
|
240
278
|
|
|
241
279
|
protected onDragStart(e: DragEvent): void {
|
|
242
280
|
this.dragging = true
|
|
243
281
|
const point = this.dragPoint = e.current as IEditPoint, { pointType } = point
|
|
244
|
-
const { editor, dragStartData } = this, {
|
|
282
|
+
const { editor, dragStartData } = this, { target } = this, { moveable, resizeable, rotateable, skewable, hideOnMove } = this.mergeConfig
|
|
283
|
+
|
|
284
|
+
// 确定模式
|
|
245
285
|
if (point.name === 'rect') {
|
|
246
|
-
this.moving = true
|
|
247
|
-
editor.opacity =
|
|
286
|
+
moveable && (this.moving = true)
|
|
287
|
+
editor.opacity = hideOnMove ? 0 : 1 // move
|
|
288
|
+
} else {
|
|
289
|
+
if (pointType.includes('rotate') || e.metaKey || e.ctrlKey || !resizeable) {
|
|
290
|
+
rotateable && (this.rotating = true)
|
|
291
|
+
if (pointType === 'resize-rotate') resizeable && (this.resizing = true)
|
|
292
|
+
else if (point.name === 'resize-line') skewable && (this.skewing = true), this.rotating = false
|
|
293
|
+
} else if (pointType === 'resize') resizeable && (this.resizing = true)
|
|
294
|
+
if (pointType === 'skew') skewable && (this.skewing = true)
|
|
248
295
|
}
|
|
296
|
+
|
|
249
297
|
dragStartData.x = e.x
|
|
250
298
|
dragStartData.y = e.y
|
|
251
|
-
dragStartData.point = { x:
|
|
252
|
-
dragStartData.bounds = { ...
|
|
253
|
-
dragStartData.rotation =
|
|
299
|
+
dragStartData.point = { x: target.x, y: target.y } // 用于移动
|
|
300
|
+
dragStartData.bounds = { ...target.getLayoutBounds('box', 'local') } // 用于resize
|
|
301
|
+
dragStartData.rotation = target.rotation // 用于旋转
|
|
254
302
|
if (pointType && pointType.includes('resize')) ResizeEvent.resizingKeys = editor.leafList.keys // 记录正在resize中的元素列表
|
|
255
303
|
}
|
|
256
304
|
|
|
257
305
|
protected onDragEnd(e: DragEvent): void {
|
|
258
|
-
this.dragging = false
|
|
259
306
|
this.dragPoint = null
|
|
260
|
-
this.
|
|
307
|
+
this.resetDoing()
|
|
261
308
|
const { name, pointType } = e.current as IEditPoint
|
|
262
309
|
if (name === 'rect') this.editor.opacity = 1 // move
|
|
263
310
|
if (pointType && pointType.includes('resize')) ResizeEvent.resizingKeys = null
|
|
264
311
|
}
|
|
265
312
|
|
|
266
313
|
protected onDrag(e: DragEvent): void {
|
|
267
|
-
const {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
314
|
+
const { transformTool, moving, resizing, rotating, skewing } = this
|
|
315
|
+
if (moving) {
|
|
316
|
+
transformTool.onMove(e)
|
|
317
|
+
updateMoveCursor(this)
|
|
318
|
+
} else if (resizing || rotating || skewing) {
|
|
319
|
+
const point = e.current as IEditPoint
|
|
320
|
+
if (point.pointType) this.enterPoint = point// 防止变化
|
|
321
|
+
if (rotating) transformTool.onRotate(e)
|
|
322
|
+
if (resizing) transformTool.onScale(e)
|
|
323
|
+
if (skewing) transformTool.onSkew(e)
|
|
324
|
+
updatePointCursor(this, e)
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
protected resetDoing(): void {
|
|
329
|
+
if (this.canUse) this.dragging = this.gesturing = this.moving = this.resizing = this.rotating = this.skewing = false
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// 手势控制元素
|
|
333
|
+
|
|
334
|
+
public onMove(e: MoveEvent): void {
|
|
335
|
+
if (this.canGesture && e.moveType !== 'drag') {
|
|
336
|
+
e.stop()
|
|
337
|
+
if (typeof this.mergeConfig.moveable === 'string') {
|
|
338
|
+
this.gesturing = this.moving = true
|
|
339
|
+
this.transformTool.onMove(e)
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
public onScale(e: ZoomEvent): void {
|
|
345
|
+
if (this.canGesture) {
|
|
346
|
+
e.stop()
|
|
347
|
+
if (typeof this.mergeConfig.resizeable === 'string') {
|
|
348
|
+
this.gesturing = this.resizing = true
|
|
349
|
+
this.transformTool.onScale(e)
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
public onRotate(e: RotateEvent): void {
|
|
355
|
+
if (this.canGesture) {
|
|
356
|
+
e.stop()
|
|
357
|
+
if (typeof this.mergeConfig.rotateable === 'string') {
|
|
358
|
+
this.gesturing = this.rotating = true
|
|
359
|
+
this.transformTool.onRotate(e)
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// 键盘
|
|
365
|
+
|
|
366
|
+
protected onKey(e: KeyEvent): void {
|
|
367
|
+
updatePointCursor(this, e)
|
|
275
368
|
}
|
|
276
369
|
|
|
277
370
|
public onArrow(e: IKeyEvent): void {
|
|
278
|
-
const { editor } = this
|
|
279
|
-
if (editor.editing &&
|
|
371
|
+
const { editor, transformTool } = this
|
|
372
|
+
if (this.canUse && editor.editing && this.mergeConfig.keyEvent) {
|
|
280
373
|
let x = 0, y = 0
|
|
281
374
|
const distance = e.shiftKey ? 10 : 1
|
|
282
375
|
switch (e.code) {
|
|
@@ -292,32 +385,33 @@ export class EditBox extends Group implements IEditBox {
|
|
|
292
385
|
case 'ArrowRight':
|
|
293
386
|
x = distance
|
|
294
387
|
}
|
|
295
|
-
if (x || y)
|
|
388
|
+
if (x || y) transformTool.move(x, y)
|
|
296
389
|
}
|
|
297
390
|
}
|
|
298
391
|
|
|
299
392
|
|
|
300
393
|
protected onDoubleTap(e: PointerEvent): void {
|
|
301
|
-
|
|
394
|
+
const { openInner, preventEditInner } = this.mergeConfig
|
|
395
|
+
if (openInner === 'double' && !preventEditInner) this.openInner(e)
|
|
302
396
|
}
|
|
303
397
|
|
|
304
398
|
protected onLongPress(e: PointerEvent): void {
|
|
305
|
-
|
|
399
|
+
const { openInner, preventEditInner } = this.mergeConfig
|
|
400
|
+
if (openInner === 'long' && preventEditInner) this.openInner(e)
|
|
306
401
|
}
|
|
307
402
|
|
|
308
403
|
protected openInner(e: PointerEvent): void {
|
|
309
|
-
const { editor } = this
|
|
310
|
-
if (
|
|
311
|
-
|
|
312
|
-
if (
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
const { children } = element
|
|
404
|
+
const { editor, target } = this
|
|
405
|
+
if (this.single) {
|
|
406
|
+
if (target.locked) return
|
|
407
|
+
if (target.isBranch && !target.editInner) {
|
|
408
|
+
if ((target as IBox).textBox) {
|
|
409
|
+
const { children } = target
|
|
316
410
|
const find = children.find(item => item.editable && item instanceof Text) || children.find(item => item instanceof Text)
|
|
317
411
|
if (find) return editor.openInnerEditor(find) // 文本Box直接进入编辑状态,如便利贴文本
|
|
318
412
|
}
|
|
319
413
|
|
|
320
|
-
editor.openGroup(
|
|
414
|
+
editor.openGroup(target as IGroup)
|
|
321
415
|
editor.target = editor.selector.findDeepOne(e)
|
|
322
416
|
} else {
|
|
323
417
|
editor.openInnerEditor()
|
|
@@ -327,7 +421,6 @@ export class EditBox extends Group implements IEditBox {
|
|
|
327
421
|
|
|
328
422
|
|
|
329
423
|
public listenPointEvents(point: IEditPoint, type: IEditPointType, direction: Direction9): void {
|
|
330
|
-
const { editor } = this
|
|
331
424
|
point.direction = direction
|
|
332
425
|
point.pointType = type
|
|
333
426
|
|
|
@@ -337,25 +430,39 @@ export class EditBox extends Group implements IEditBox {
|
|
|
337
430
|
[DragEvent.END, this.onDragEnd, this],
|
|
338
431
|
[PointerEvent.LEAVE, () => { this.enterPoint = null }],
|
|
339
432
|
]
|
|
340
|
-
if (point.name !== 'circle') events.push([PointerEvent.ENTER, (e: PointerEvent) => { this.enterPoint = point,
|
|
433
|
+
if (point.name !== 'circle') events.push([PointerEvent.ENTER, (e: PointerEvent) => { this.enterPoint = point, updatePointCursor(this, e) }])
|
|
341
434
|
this.__eventIds.push(point.on_(events))
|
|
342
435
|
}
|
|
343
436
|
|
|
344
437
|
protected __listenEvents(): void {
|
|
345
|
-
const { rect, editor } = this
|
|
346
|
-
this.__eventIds.push(
|
|
347
|
-
editor.on_(EditorEvent.SELECT, this.onSelect, this),
|
|
438
|
+
const { rect, editor, __eventIds: events } = this
|
|
348
439
|
|
|
440
|
+
events.push(
|
|
349
441
|
rect.on_([
|
|
350
442
|
[DragEvent.START, this.onDragStart, this],
|
|
351
|
-
[DragEvent.DRAG,
|
|
443
|
+
[DragEvent.DRAG, this.onDrag, this],
|
|
352
444
|
[DragEvent.END, this.onDragEnd, this],
|
|
353
445
|
|
|
354
|
-
[PointerEvent.ENTER, () => updateMoveCursor(
|
|
446
|
+
[PointerEvent.ENTER, () => updateMoveCursor(this)],
|
|
355
447
|
[PointerEvent.DOUBLE_TAP, this.onDoubleTap, this],
|
|
356
448
|
[PointerEvent.LONG_PRESS, this.onLongPress, this]
|
|
357
449
|
])
|
|
358
450
|
)
|
|
451
|
+
|
|
452
|
+
this.waitLeafer(() => {
|
|
453
|
+
events.push(
|
|
454
|
+
editor.app.on_([
|
|
455
|
+
[[KeyEvent.HOLD, KeyEvent.UP], this.onKey, this],
|
|
456
|
+
[KeyEvent.DOWN, this.onArrow, this],
|
|
457
|
+
[MoveEvent.BEFORE_MOVE, this.onMove, this, true],
|
|
458
|
+
[ZoomEvent.BEFORE_ZOOM, this.onScale, this, true],
|
|
459
|
+
[RotateEvent.BEFORE_ROTATE, this.onRotate, this, true],
|
|
460
|
+
[MoveEvent.END, this.resetDoing, this],
|
|
461
|
+
[ZoomEvent.END, this.resetDoing, this],
|
|
462
|
+
[RotateEvent.END, this.resetDoing, this],
|
|
463
|
+
])
|
|
464
|
+
)
|
|
465
|
+
})
|
|
359
466
|
}
|
|
360
467
|
|
|
361
468
|
protected __removeListenEvents(): void {
|
package/src/display/EditMask.ts
CHANGED
|
@@ -29,10 +29,11 @@ export class EditMask extends UI {
|
|
|
29
29
|
if (options.bounds && !options.bounds.hit(editor.editBox.rect.__world, options.matrix)) return
|
|
30
30
|
|
|
31
31
|
canvas.saveBlendMode('destination-out')
|
|
32
|
+
options = { ...options, shape: true }
|
|
32
33
|
editor.list.forEach(item => {
|
|
33
|
-
item.
|
|
34
|
-
const {
|
|
35
|
-
if (
|
|
34
|
+
item.__render(canvas, options)
|
|
35
|
+
const { parent } = item
|
|
36
|
+
if (parent && (parent as IBox).textBox) parent.__renderShape(canvas, options) // 文本框
|
|
36
37
|
})
|
|
37
38
|
canvas.restoreBlendMode()
|
|
38
39
|
}
|
|
@@ -54,16 +54,16 @@ export class EditSelect extends Group implements IEditSelect {
|
|
|
54
54
|
|
|
55
55
|
protected onSelect(): void {
|
|
56
56
|
if (this.running) {
|
|
57
|
-
|
|
58
|
-
const { stroke, strokeWidth, selectedStyle } = mergeConfig
|
|
59
|
-
this.targetStroker.setTarget(list, { stroke, strokeWidth: Math.max(1, strokeWidth / 2), ...(selectedStyle || {}) })
|
|
57
|
+
this.targetStroker.setTarget(this.editor.list)
|
|
60
58
|
this.hoverStroker.target = null
|
|
61
59
|
}
|
|
62
60
|
}
|
|
63
61
|
|
|
64
62
|
public update(): void {
|
|
65
63
|
this.hoverStroker.update()
|
|
66
|
-
|
|
64
|
+
|
|
65
|
+
const { stroke, strokeWidth, selectedStyle } = this.editor.mergedConfig
|
|
66
|
+
this.targetStroker.update({ stroke, strokeWidth: strokeWidth && Math.max(1, strokeWidth / 2), ...(selectedStyle || {}) })
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
// move / down
|
package/src/display/Stroker.ts
CHANGED
|
@@ -27,16 +27,17 @@ export class Stroker extends UI implements IStroker {
|
|
|
27
27
|
this.strokeAlign = 'center'
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
public setTarget(target: IUI | IUI[], style
|
|
31
|
-
this.set(style)
|
|
30
|
+
public setTarget(target: IUI | IUI[], style?: IRectInputData): void {
|
|
31
|
+
if (style) this.set(style)
|
|
32
32
|
this.target = target
|
|
33
33
|
this.update()
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
public update(): void {
|
|
36
|
+
public update(style?: IRectInputData): void {
|
|
37
37
|
const { list } = this
|
|
38
38
|
if (list.length) {
|
|
39
39
|
setListWithFn(bounds, list, worldBounds)
|
|
40
|
+
if (style) this.set(style)
|
|
40
41
|
this.set(bounds)
|
|
41
42
|
this.visible = true
|
|
42
43
|
} else this.visible = 0
|
package/src/editor/cursor.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IObject, IUIEvent } from '@leafer-ui/interface'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { IEditBox } from '@leafer-in/interface'
|
|
4
4
|
import { MathHelper } from '@leafer-ui/draw'
|
|
5
5
|
|
|
6
6
|
import { EditDataHelper } from '../helper/EditDataHelper'
|
|
@@ -8,9 +8,9 @@ import { EditDataHelper } from '../helper/EditDataHelper'
|
|
|
8
8
|
|
|
9
9
|
const cacheCursors: IObject = {}
|
|
10
10
|
|
|
11
|
-
export function
|
|
12
|
-
const {
|
|
13
|
-
if (!point || !editor.editing || !editBox.
|
|
11
|
+
export function updatePointCursor(editBox: IEditBox, e: IUIEvent): void {
|
|
12
|
+
const { enterPoint: point, dragging, skewing, resizing, flippedX, flippedY } = editBox
|
|
13
|
+
if (!point || !editBox.editor.editing || !editBox.canUse) return
|
|
14
14
|
if (point.name === 'circle') return // 独立旋转按钮
|
|
15
15
|
if (point.pointType === 'button') { // 普通按钮
|
|
16
16
|
if (!point.cursor) point.cursor = 'pointer'
|
|
@@ -18,14 +18,16 @@ export function updateCursor(editor: IEditor, e: IUIEvent): void {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
let { rotation } = editBox
|
|
21
|
-
const { resizeCursor, rotateCursor, skewCursor, resizeable, rotateable, skewable } =
|
|
22
|
-
const { pointType } = point, { flippedX, flippedY } = editBox
|
|
21
|
+
const { pointType } = point, { resizeCursor, rotateCursor, skewCursor, resizeable, rotateable, skewable } = editBox.mergeConfig
|
|
23
22
|
|
|
24
23
|
let showResize = pointType.includes('resize')
|
|
25
24
|
if (showResize && rotateable && (e.metaKey || e.ctrlKey || !resizeable)) showResize = false
|
|
26
25
|
const showSkew = skewable && !showResize && (point.name === 'resize-line' || pointType === 'skew')
|
|
27
26
|
|
|
28
|
-
const cursor =
|
|
27
|
+
const cursor = dragging
|
|
28
|
+
? (skewing ? skewCursor : (resizing ? resizeCursor : rotateCursor))
|
|
29
|
+
: (showSkew ? skewCursor : (showResize ? resizeCursor : rotateCursor))
|
|
30
|
+
|
|
29
31
|
rotation += (EditDataHelper.getFlipDirection(point.direction, flippedX, flippedY) + 1) * 45
|
|
30
32
|
rotation = Math.round(MathHelper.formatRotation(rotation, true) / 2) * 2
|
|
31
33
|
|
|
@@ -39,9 +41,9 @@ export function updateCursor(editor: IEditor, e: IUIEvent): void {
|
|
|
39
41
|
}
|
|
40
42
|
}
|
|
41
43
|
|
|
42
|
-
export function updateMoveCursor(
|
|
43
|
-
const { moveCursor, moveable } =
|
|
44
|
-
|
|
44
|
+
export function updateMoveCursor(editBox: IEditBox): void {
|
|
45
|
+
const { moveCursor, moveable } = editBox.mergeConfig
|
|
46
|
+
if (editBox.canUse) editBox.rect.cursor = moveable ? moveCursor : undefined
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
|
package/src/editor/simulate.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ILeaf } from '@leafer-ui/interface'
|
|
2
2
|
import { Bounds } from '@leafer-ui/draw'
|
|
3
3
|
|
|
4
4
|
import { IEditor } from '@leafer-in/interface'
|
|
@@ -8,7 +8,7 @@ const bounds = new Bounds()
|
|
|
8
8
|
|
|
9
9
|
export function simulate(editor: IEditor) {
|
|
10
10
|
const { simulateTarget, list } = editor
|
|
11
|
-
const { zoomLayer } = list[0].leafer
|
|
11
|
+
const { zoomLayer } = list[0].leafer // follow zoomLayer zoom / move
|
|
12
12
|
simulateTarget.safeChange(() => {
|
|
13
13
|
bounds.setListWithFn(list, (leaf: ILeaf) => leaf.getBounds('box', 'page'))
|
|
14
14
|
if (bounds.width === 0) bounds.width = 0.1 // fix
|
package/src/editor/target.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { LeafList } from '@leafer-ui/draw'
|
|
|
3
3
|
import { IEditor, IUI } from '@leafer-in/interface'
|
|
4
4
|
|
|
5
5
|
import { simulate } from './simulate'
|
|
6
|
-
import { updateMoveCursor } from './cursor'
|
|
7
6
|
import { EditorEvent } from '../event/EditorEvent'
|
|
8
7
|
|
|
9
8
|
|
|
@@ -15,23 +14,26 @@ export function onTarget(editor: IEditor, oldValue: IUI | IUI[]): void {
|
|
|
15
14
|
} else {
|
|
16
15
|
editor.simulateTarget.remove()
|
|
17
16
|
editor.leafList.reset()
|
|
18
|
-
editor.closeInnerEditor()
|
|
19
17
|
}
|
|
20
18
|
|
|
21
|
-
editor.
|
|
19
|
+
editor.closeInnerEditor(true)
|
|
20
|
+
editor.unloadEditTool()
|
|
21
|
+
|
|
22
|
+
const data = { editor, value: target, oldValue }
|
|
23
|
+
editor.emitEvent(new EditorEvent(EditorEvent.SELECT, data))
|
|
22
24
|
editor.checkOpenedGroups()
|
|
23
25
|
|
|
24
26
|
if (editor.editing) {
|
|
25
27
|
editor.waitLeafer(() => {
|
|
26
|
-
updateMoveCursor(editor)
|
|
27
28
|
editor.updateEditTool()
|
|
28
|
-
editor.update()
|
|
29
29
|
editor.listenTargetEvents()
|
|
30
30
|
})
|
|
31
31
|
} else {
|
|
32
32
|
editor.updateEditTool()
|
|
33
33
|
editor.removeTargetEvents()
|
|
34
34
|
}
|
|
35
|
+
|
|
36
|
+
editor.emitEvent(new EditorEvent(EditorEvent.AFTER_SELECT, data))
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
|
package/src/event/EditorEvent.ts
CHANGED
|
@@ -12,6 +12,7 @@ export class EditorEvent extends Event implements IEditorEvent {
|
|
|
12
12
|
|
|
13
13
|
static BEFORE_SELECT = 'editor.before_select'
|
|
14
14
|
static SELECT = 'editor.select'
|
|
15
|
+
static AFTER_SELECT = 'editor.after_select'
|
|
15
16
|
|
|
16
17
|
static BEFORE_HOVER = 'editor.before_hover'
|
|
17
18
|
static HOVER = 'editor.hover'
|