@leafer-in/editor 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/editor.cjs +164 -93
- package/dist/editor.esm.js +165 -94
- package/dist/editor.esm.min.js +1 -1
- package/dist/editor.js +164 -93
- package/dist/editor.min.cjs +1 -1
- package/dist/editor.min.js +1 -1
- package/package.json +5 -5
- package/src/Editor.ts +74 -56
- package/src/config.ts +1 -0
- package/src/display/EditBox.ts +35 -30
- package/src/display/EditMask.ts +1 -1
- package/src/display/EditSelect.ts +26 -10
- package/src/editor/cursor.ts +4 -0
- package/src/helper/EditDataHelper.ts +54 -13
- package/types/index.d.ts +13 -6
package/src/Editor.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { IGroupInputData, IUI, IEventListenerId, IPointData, ILeafList, IEditSize, IGroup, IObject, IAlign } from '@leafer-ui/interface'
|
|
1
|
+
import { IGroupInputData, IUI, IEventListenerId, IPointData, ILeafList, IEditSize, IGroup, IObject, IAlign, IAxis, IFunction, ILayoutBoundsData } from '@leafer-ui/interface'
|
|
2
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
|
+
import { DragEvent, RotateEvent, KeyEvent, ZoomEvent, MoveEvent } from '@leafer-ui/core'
|
|
4
4
|
|
|
5
5
|
import { IEditBox, IEditPoint, IEditor, IEditorConfig, IEditTool, IEditorScaleEvent, IInnerEditor } from '@leafer-in/interface'
|
|
6
6
|
|
|
@@ -75,6 +75,7 @@ export class Editor extends Group implements IEditor {
|
|
|
75
75
|
public editMask: EditMask = new EditMask(this)
|
|
76
76
|
|
|
77
77
|
public dragStartPoint: IPointData
|
|
78
|
+
public dragStartBounds: ILayoutBoundsData
|
|
78
79
|
|
|
79
80
|
public targetEventIds: IEventListenerId[] = []
|
|
80
81
|
|
|
@@ -153,32 +154,47 @@ export class Editor extends Group implements IEditor {
|
|
|
153
154
|
|
|
154
155
|
// operate
|
|
155
156
|
|
|
156
|
-
public onMove(e: DragEvent): void {
|
|
157
|
-
|
|
157
|
+
public onMove(e: DragEvent | MoveEvent): void {
|
|
158
|
+
|
|
159
|
+
if (e instanceof MoveEvent) {
|
|
160
|
+
|
|
161
|
+
if (e.moveType !== 'drag') {
|
|
162
|
+
const { moveable, resizeable } = this.mergeConfig
|
|
163
|
+
const move = e.getLocalMove(this.element)
|
|
164
|
+
if (moveable === 'move') e.stop(), this.move(move.x, move.y)
|
|
165
|
+
else if (resizeable === 'zoom') e.stop()
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
} else {
|
|
169
|
+
|
|
170
|
+
const total = { x: e.totalX, y: e.totalY }
|
|
171
|
+
|
|
172
|
+
if (e.shiftKey) {
|
|
173
|
+
if (Math.abs(total.x) > Math.abs(total.y)) total.y = 0
|
|
174
|
+
else total.x = 0
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
this.move(DragEvent.getValidMove(this.element, this.dragStartPoint, total))
|
|
158
178
|
|
|
159
|
-
if (e.shiftKey) {
|
|
160
|
-
if (Math.abs(total.x) > Math.abs(total.y)) total.y = 0
|
|
161
|
-
else total.x = 0
|
|
162
179
|
}
|
|
163
180
|
|
|
164
|
-
this.move(DragEvent.getValidMove(this.element, this.dragStartPoint, total))
|
|
165
181
|
}
|
|
166
182
|
|
|
167
183
|
public onScale(e: DragEvent | ZoomEvent): void {
|
|
168
184
|
const { element } = this
|
|
185
|
+
let { around, lockRatio, resizeable, flipable, editSize } = this.mergeConfig
|
|
169
186
|
|
|
170
187
|
if (e instanceof ZoomEvent) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
188
|
+
|
|
189
|
+
if (resizeable === 'zoom') e.stop(), this.scaleOf(element.getInnerPoint(e), e.scale, e.scale)
|
|
190
|
+
|
|
175
191
|
} else {
|
|
176
192
|
|
|
177
193
|
const { direction } = e.current as IEditPoint
|
|
178
|
-
|
|
194
|
+
|
|
179
195
|
if (e.shiftKey || element.lockRatio) lockRatio = true
|
|
180
196
|
|
|
181
|
-
const data = EditDataHelper.getScaleData(element.
|
|
197
|
+
const data = EditDataHelper.getScaleData(element, this.dragStartBounds, direction, e.getInnerTotal(element), lockRatio, EditDataHelper.getAround(around, e.altKey), flipable, this.multiple || editSize === 'scale')
|
|
182
198
|
|
|
183
199
|
if (this.editTool.onScaleWithDrag) {
|
|
184
200
|
data.drag = e
|
|
@@ -192,7 +208,7 @@ export class Editor extends Group implements IEditor {
|
|
|
192
208
|
}
|
|
193
209
|
|
|
194
210
|
public onRotate(e: DragEvent | RotateEvent): void {
|
|
195
|
-
const { skewable, around, rotateGap } = this.mergeConfig
|
|
211
|
+
const { skewable, rotateable, around, rotateGap } = this.mergeConfig
|
|
196
212
|
const { direction, name } = e.current as IEditPoint
|
|
197
213
|
if (skewable && name === 'resize-line') return this.onSkew(e as DragEvent)
|
|
198
214
|
|
|
@@ -200,15 +216,17 @@ export class Editor extends Group implements IEditor {
|
|
|
200
216
|
let origin: IPointData, rotation: number
|
|
201
217
|
|
|
202
218
|
if (e instanceof RotateEvent) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
219
|
+
|
|
220
|
+
if (rotateable === 'rotate') e.stop(), rotation = e.rotation, origin = element.getInnerPoint(e)
|
|
221
|
+
else return
|
|
222
|
+
|
|
207
223
|
} else {
|
|
224
|
+
|
|
208
225
|
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'))
|
|
226
|
+
const data = EditDataHelper.getRotateData(element.boxBounds, direction, e.getInner(element), element.getInnerPoint(last), e.shiftKey ? null : (element.around || element.origin || around || 'center'))
|
|
210
227
|
rotation = data.rotation
|
|
211
228
|
origin = data.origin
|
|
229
|
+
|
|
212
230
|
}
|
|
213
231
|
|
|
214
232
|
rotation = MathHelper.getGapRotation(rotation, rotateGap, element.rotation)
|
|
@@ -250,77 +268,74 @@ export class Editor extends Group implements IEditor {
|
|
|
250
268
|
if (!this.mergeConfig.resizeable || this.element.locked) return
|
|
251
269
|
|
|
252
270
|
const { element } = this
|
|
253
|
-
const
|
|
254
|
-
const event = new EditorScaleEvent(EditorScaleEvent.SCALE, { ...data, target: element, editor: this, worldOrigin })
|
|
271
|
+
const event = new EditorScaleEvent(EditorScaleEvent.SCALE, { ...data, target: element, editor: this, worldOrigin: element.getWorldPoint(data.origin) })
|
|
255
272
|
|
|
256
273
|
this.editTool.onScaleWithDrag(event)
|
|
257
274
|
this.emitEvent(event)
|
|
258
275
|
}
|
|
259
276
|
|
|
260
277
|
|
|
261
|
-
|
|
278
|
+
override scaleOf(origin: IPointData | IAlign, scaleX: number, scaleY = scaleX, _resize?: boolean): void {
|
|
262
279
|
if (!this.mergeConfig.resizeable || this.element.locked) return
|
|
263
280
|
|
|
264
281
|
const { element } = this
|
|
265
|
-
const worldOrigin =
|
|
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
|
-
|
|
282
|
+
const worldOrigin = this.getWorldOrigin(origin)
|
|
283
|
+
const transform = this.multiple && this.getChangedTransform(() => element.scaleOf(origin, scaleX, scaleY))
|
|
275
284
|
const event = new EditorScaleEvent(EditorScaleEvent.SCALE, { target: element, editor: this, worldOrigin, scaleX, scaleY, transform })
|
|
276
285
|
|
|
277
286
|
this.editTool.onScale(event)
|
|
278
287
|
this.emitEvent(event)
|
|
279
288
|
}
|
|
280
289
|
|
|
281
|
-
|
|
282
|
-
if (
|
|
290
|
+
override flip(axis: IAxis): void {
|
|
291
|
+
if (this.element.locked) return
|
|
283
292
|
|
|
284
293
|
const { element } = this
|
|
285
|
-
const worldOrigin =
|
|
286
|
-
|
|
294
|
+
const worldOrigin = this.getWorldOrigin('center')
|
|
295
|
+
const transform = this.multiple ? this.getChangedTransform(() => element.flip(axis)) : new Matrix(LeafHelper.getFlipTransform(element, axis))
|
|
296
|
+
const event = new EditorScaleEvent(EditorScaleEvent.SCALE, { target: element, editor: this, worldOrigin, scaleX: axis === 'x' ? -1 : 1, scaleY: axis === 'y' ? -1 : 1, transform })
|
|
287
297
|
|
|
288
|
-
|
|
298
|
+
this.editTool.onScale(event)
|
|
299
|
+
this.emitEvent(event)
|
|
300
|
+
}
|
|
289
301
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
element.rotateOf(origin, rotation)
|
|
293
|
-
transform = new Matrix(element.worldTransform).divide(oldMatrix) // world change transform
|
|
294
|
-
}
|
|
302
|
+
override rotateOf(origin: IPointData | IAlign, rotation: number): void {
|
|
303
|
+
if (!this.mergeConfig.rotateable || this.element.locked) return
|
|
295
304
|
|
|
305
|
+
const { element } = this
|
|
306
|
+
const worldOrigin = this.getWorldOrigin(origin)
|
|
307
|
+
const transform = this.multiple && this.getChangedTransform(() => element.rotateOf(origin, rotation))
|
|
296
308
|
const event = new EditorRotateEvent(EditorRotateEvent.ROTATE, { target: element, editor: this, worldOrigin, rotation, transform })
|
|
297
309
|
|
|
298
310
|
this.editTool.onRotate(event)
|
|
299
311
|
this.emitEvent(event)
|
|
300
312
|
}
|
|
301
313
|
|
|
302
|
-
|
|
314
|
+
override skewOf(origin: IPointData | IAlign, skewX: number, skewY = 0, _resize?: boolean): void {
|
|
303
315
|
if (!this.mergeConfig.skewable || this.element.locked) return
|
|
304
316
|
|
|
305
317
|
const { element } = this
|
|
306
|
-
const worldOrigin =
|
|
318
|
+
const worldOrigin = this.getWorldOrigin(origin)
|
|
319
|
+
const transform = this.multiple && this.getChangedTransform(() => element.skewOf(origin, skewX, skewY))
|
|
320
|
+
const event = new EditorSkewEvent(EditorSkewEvent.SKEW, { target: element, editor: this, worldOrigin, skewX, skewY, transform })
|
|
307
321
|
|
|
308
|
-
|
|
322
|
+
this.editTool.onSkew(event)
|
|
323
|
+
this.emitEvent(event)
|
|
324
|
+
}
|
|
309
325
|
|
|
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
326
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
327
|
+
protected getWorldOrigin(origin: IPointData | IAlign): IPointData {
|
|
328
|
+
return this.element.getWorldPoint(LeafHelper.getInnerOrigin(this.element, origin))
|
|
329
|
+
}
|
|
319
330
|
|
|
320
|
-
|
|
321
|
-
this
|
|
331
|
+
protected getChangedTransform(func: IFunction): Matrix {
|
|
332
|
+
const { element } = this
|
|
333
|
+
const oldMatrix = new Matrix(element.worldTransform)
|
|
334
|
+
func()
|
|
335
|
+
return new Matrix(element.worldTransform).divide(oldMatrix) // world change transform
|
|
322
336
|
}
|
|
323
337
|
|
|
338
|
+
|
|
324
339
|
// group
|
|
325
340
|
|
|
326
341
|
public group(userGroup?: IGroup | IGroupInputData): IGroup {
|
|
@@ -455,6 +470,9 @@ export class Editor extends Group implements IEditor {
|
|
|
455
470
|
if (!this.targetEventIds.length) {
|
|
456
471
|
const { leafer } = this.list[0]
|
|
457
472
|
this.targetEventIds = [
|
|
473
|
+
this.app.on_(MoveEvent.BEFORE_MOVE, this.onMove, this, true),
|
|
474
|
+
this.app.on_(ZoomEvent.BEFORE_ZOOM, this.onScale, this, true),
|
|
475
|
+
this.app.on_(RotateEvent.BEFORE_ROTATE, this.onRotate, this, true),
|
|
458
476
|
leafer.on_(RenderEvent.START, this.update, this),
|
|
459
477
|
leafer.on_([KeyEvent.HOLD, KeyEvent.UP], (e: KeyEvent) => { updateCursor(this, e) }),
|
|
460
478
|
leafer.on_(KeyEvent.DOWN, this.editBox.onArrow, this.editBox)
|
package/src/config.ts
CHANGED
package/src/display/EditBox.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { IRect, IEventListenerId, IBoundsData, IPointData, IKeyEvent, IGroup, IBox, IBoxInputData, IAlign } from '@leafer-ui/interface'
|
|
1
|
+
import { IRect, IEventListenerId, IBoundsData, IPointData, IKeyEvent, IGroup, IBox, IBoxInputData, IAlign, IUI, IEditorConfig } from '@leafer-ui/interface'
|
|
2
2
|
import { Group, Box, AroundHelper, Direction9 } from '@leafer-ui/draw'
|
|
3
|
-
import { DragEvent, PointerEvent
|
|
3
|
+
import { DragEvent, PointerEvent } from '@leafer-ui/core'
|
|
4
4
|
|
|
5
5
|
import { IEditBox, IEditor, IEditPoint, IEditPointType } from '@leafer-in/interface'
|
|
6
6
|
|
|
@@ -22,7 +22,6 @@ export class EditBox extends Group implements IEditBox {
|
|
|
22
22
|
|
|
23
23
|
public rect: IBox = new Box({ name: 'rect', hitFill: 'all', hitStroke: 'none', strokeAlign: 'center', hitRadius: 5 }) // target rect
|
|
24
24
|
public circle: IEditPoint = new EditPoint({ name: 'circle', strokeAlign: 'center', around: 'center', cursor: 'crosshair', hitRadius: 5 }) // rotate point
|
|
25
|
-
|
|
26
25
|
public buttons: IGroup = new Group({ around: 'center', hitSelf: false })
|
|
27
26
|
|
|
28
27
|
public resizePoints: IEditPoint[] = [] // topLeft, top, topRight, right, bottomRight, bottom, bottomLeft, left
|
|
@@ -69,10 +68,9 @@ export class EditBox extends Group implements IEditBox {
|
|
|
69
68
|
this.listenPointEvents(resizePoint, 'resize', i)
|
|
70
69
|
}
|
|
71
70
|
|
|
72
|
-
buttons.add(circle)
|
|
73
71
|
this.listenPointEvents(circle, 'rotate', 2)
|
|
74
72
|
|
|
75
|
-
view.addMany(...rotatePoints, rect, buttons, ...resizeLines, ...resizePoints)
|
|
73
|
+
view.addMany(...rotatePoints, rect, circle, buttons, ...resizeLines, ...resizePoints)
|
|
76
74
|
this.add(view)
|
|
77
75
|
}
|
|
78
76
|
|
|
@@ -93,11 +91,11 @@ export class EditBox extends Group implements IEditBox {
|
|
|
93
91
|
}
|
|
94
92
|
|
|
95
93
|
// rotate
|
|
96
|
-
circle.set(this.getPointStyle(mergeConfig.rotatePoint || pointsStyle[0]))
|
|
94
|
+
circle.set(this.getPointStyle(mergeConfig.circle || mergeConfig.rotatePoint || pointsStyle[0]))
|
|
97
95
|
|
|
98
96
|
// rect
|
|
99
97
|
rect.set({ stroke, strokeWidth, ...(mergeConfig.rect || {}) })
|
|
100
|
-
rect.hittable = !single && moveable
|
|
98
|
+
rect.hittable = !single && !!moveable
|
|
101
99
|
|
|
102
100
|
// 编辑框作为底部虚拟元素, 在 onSelect 方法移除
|
|
103
101
|
element.syncEventer = (single && moveable) ? rect : null
|
|
@@ -111,7 +109,7 @@ export class EditBox extends Group implements IEditBox {
|
|
|
111
109
|
if (this.view.worldOpacity) {
|
|
112
110
|
const { mergeConfig } = this.editor
|
|
113
111
|
const { width, height } = bounds
|
|
114
|
-
const { rect, circle, resizePoints, rotatePoints, resizeLines } = this
|
|
112
|
+
const { rect, circle, buttons, resizePoints, rotatePoints, resizeLines } = this
|
|
115
113
|
const { middlePoint, resizeable, rotateable, hideOnSmall } = mergeConfig
|
|
116
114
|
|
|
117
115
|
const smallSize = typeof hideOnSmall === 'number' ? hideOnSmall : 10
|
|
@@ -150,36 +148,50 @@ export class EditBox extends Group implements IEditBox {
|
|
|
150
148
|
}
|
|
151
149
|
|
|
152
150
|
// rotate
|
|
153
|
-
circle.visible = showPoints && rotateable && !!mergeConfig.rotatePoint
|
|
151
|
+
circle.visible = showPoints && rotateable && !!(mergeConfig.circle || mergeConfig.rotatePoint)
|
|
152
|
+
if (circle.visible) this.layoutCircle(mergeConfig)
|
|
154
153
|
|
|
155
154
|
// rect
|
|
156
155
|
if (rect.path) rect.path = null // line可能会变成path优先模式
|
|
157
156
|
rect.set({ ...bounds, visible: true })
|
|
158
157
|
|
|
159
158
|
// buttons
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
if (buttonVisible) this.layoutButtons()
|
|
159
|
+
buttons.visible = showPoints && buttons.children.length > 0
|
|
160
|
+
if (buttons.visible) this.layoutButtons(mergeConfig)
|
|
163
161
|
}
|
|
164
162
|
}
|
|
165
163
|
|
|
166
|
-
protected
|
|
167
|
-
const {
|
|
168
|
-
const
|
|
164
|
+
protected layoutCircle(config: IEditorConfig): void {
|
|
165
|
+
const { circleDirection, circleMargin, buttonsMargin, buttonsDirection, middlePoint } = config
|
|
166
|
+
const direction = fourDirection.indexOf(circleDirection || ((this.buttons.children.length && buttonsDirection === 'bottom') ? 'top' : 'bottom'))
|
|
167
|
+
this.setButtonPosition(this.circle, direction, circleMargin || buttonsMargin, !!middlePoint)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
protected layoutButtons(config: IEditorConfig): void {
|
|
171
|
+
const { buttons } = this
|
|
172
|
+
const { buttonsDirection, buttonsFixed, buttonsMargin, middlePoint } = config
|
|
169
173
|
|
|
170
174
|
const { flippedX, flippedY } = this
|
|
171
175
|
let index = fourDirection.indexOf(buttonsDirection)
|
|
172
176
|
if ((index % 2 && flippedX) || ((index + 1) % 2 && flippedY)) {
|
|
173
177
|
if (buttonsFixed) index = (index + 2) % 4 // flip x / y
|
|
174
178
|
}
|
|
179
|
+
|
|
175
180
|
const direction = buttonsFixed ? EditDataHelper.getRotateDirection(index, this.flippedOne ? this.rotation : -this.rotation, 4) : index
|
|
181
|
+
this.setButtonPosition(buttons, direction, buttonsMargin, !!middlePoint)
|
|
176
182
|
|
|
177
|
-
|
|
183
|
+
if (buttonsFixed) buttons.rotation = (direction - index) * 90
|
|
184
|
+
buttons.scaleX = flippedX ? -1 : 1
|
|
185
|
+
buttons.scaleY = flippedY ? -1 : 1
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
protected setButtonPosition(buttons: IUI, direction: number, buttonsMargin: number, useMiddlePoint: boolean): void {
|
|
189
|
+
const point = this.resizePoints[direction * 2 + 1] // 4 map 8 direction
|
|
178
190
|
const useX = direction % 2 // left / right
|
|
179
191
|
const sign = (!direction || direction === 3) ? -1 : 1 // top / left = -1
|
|
180
192
|
|
|
181
|
-
const useWidth =
|
|
182
|
-
const margin = (buttonsMargin + (useWidth ? ((
|
|
193
|
+
const useWidth = direction % 2 // left / right origin direction
|
|
194
|
+
const margin = (buttonsMargin + (useWidth ? ((useMiddlePoint ? point.width : 0) + buttons.boxBounds.width) : ((useMiddlePoint ? point.height : 0) + buttons.boxBounds.height)) / 2) * sign
|
|
183
195
|
|
|
184
196
|
if (useX) {
|
|
185
197
|
buttons.x = point.x + margin
|
|
@@ -188,15 +200,9 @@ export class EditBox extends Group implements IEditBox {
|
|
|
188
200
|
buttons.x = point.x
|
|
189
201
|
buttons.y = point.y + margin
|
|
190
202
|
}
|
|
191
|
-
|
|
192
|
-
if (buttonsFixed) {
|
|
193
|
-
buttons.rotation = (direction - index) * 90
|
|
194
|
-
buttons.scaleX = flippedX ? -1 : 1
|
|
195
|
-
buttons.scaleY = flippedY ? -1 : 1
|
|
196
|
-
}
|
|
197
|
-
|
|
198
203
|
}
|
|
199
204
|
|
|
205
|
+
|
|
200
206
|
public unload(): void {
|
|
201
207
|
this.visible = false
|
|
202
208
|
}
|
|
@@ -229,11 +235,13 @@ export class EditBox extends Group implements IEditBox {
|
|
|
229
235
|
|
|
230
236
|
protected onDragStart(e: DragEvent): void {
|
|
231
237
|
this.dragging = true
|
|
238
|
+
const { editor } = this
|
|
232
239
|
if (e.current.name === 'rect') {
|
|
233
|
-
const { editor } = this
|
|
234
240
|
this.moving = true
|
|
235
241
|
editor.dragStartPoint = { x: editor.element.x, y: editor.element.y }
|
|
236
242
|
editor.opacity = editor.mergeConfig.hideOnMove ? 0 : 1 // move
|
|
243
|
+
} else if ((e.current as IEditPoint).pointType === 'resize') {
|
|
244
|
+
editor.dragStartBounds = { ...editor.element.getLayoutBounds('box', 'local') }
|
|
237
245
|
}
|
|
238
246
|
}
|
|
239
247
|
|
|
@@ -249,7 +257,7 @@ export class EditBox extends Group implements IEditBox {
|
|
|
249
257
|
const point = this.enterPoint = e.current as IEditPoint
|
|
250
258
|
if (point.pointType === 'rotate' || e.metaKey || e.ctrlKey || !editor.mergeConfig.resizeable) {
|
|
251
259
|
if (editor.mergeConfig.rotateable) editor.onRotate(e)
|
|
252
|
-
} else {
|
|
260
|
+
} else if (point.pointType === 'resize') {
|
|
253
261
|
editor.onScale(e)
|
|
254
262
|
}
|
|
255
263
|
updateCursor(editor, e)
|
|
@@ -319,9 +327,6 @@ export class EditBox extends Group implements IEditBox {
|
|
|
319
327
|
rect.on_(DragEvent.DRAG, editor.onMove, editor),
|
|
320
328
|
rect.on_(DragEvent.END, this.onDragEnd, this),
|
|
321
329
|
|
|
322
|
-
rect.on_(ZoomEvent.BEFORE_ZOOM, editor.onScale, editor, true),
|
|
323
|
-
rect.on_(RotateEvent.BEFORE_ROTATE, editor.onRotate, editor, true),
|
|
324
|
-
|
|
325
330
|
rect.on_(PointerEvent.ENTER, () => updateMoveCursor(editor)),
|
|
326
331
|
rect.on_(PointerEvent.DOUBLE_TAP, this.onDoubleTap, this),
|
|
327
332
|
rect.on_(PointerEvent.LONG_PRESS, this.onLongPress, this)
|
package/src/display/EditMask.ts
CHANGED
|
@@ -23,7 +23,7 @@ export class EditMask extends UI {
|
|
|
23
23
|
const { width, height } = rect.__
|
|
24
24
|
|
|
25
25
|
canvas.resetTransform()
|
|
26
|
-
canvas.fillWorld(canvas.bounds, mask)
|
|
26
|
+
canvas.fillWorld(canvas.bounds, mask === true ? 'rgba(0,0,0,0.8)' : mask)
|
|
27
27
|
canvas.setWorld(rect.__world, options.matrix)
|
|
28
28
|
canvas.clearRect(0, 0, width, height)
|
|
29
29
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IBounds, ILeaf, ILeafList, IUI, IEventListenerId, IPointerEvent } from '@leafer-ui/interface'
|
|
1
|
+
import { IBounds, ILeaf, ILeafList, IUI, IEventListenerId, IPointerEvent, IFunction } from '@leafer-ui/interface'
|
|
2
2
|
import { Bounds, LeafList, Group } from '@leafer-ui/draw'
|
|
3
3
|
import { PointerEvent, DragEvent, MoveEvent, ZoomEvent } from '@leafer-ui/core'
|
|
4
4
|
|
|
@@ -29,8 +29,9 @@ export class EditSelect extends Group implements IEditSelect {
|
|
|
29
29
|
protected originList: ILeafList
|
|
30
30
|
protected needRemoveItem: IUI
|
|
31
31
|
|
|
32
|
-
protected
|
|
32
|
+
protected waitSelect: IFunction // 手机端延迟选中,防止多点触屏误选元素
|
|
33
33
|
|
|
34
|
+
protected __eventIds: IEventListenerId[] = []
|
|
34
35
|
|
|
35
36
|
constructor(editor: IEditor) {
|
|
36
37
|
super()
|
|
@@ -68,7 +69,7 @@ export class EditSelect extends Group implements IEditSelect {
|
|
|
68
69
|
|
|
69
70
|
protected onPointerMove(e: PointerEvent): void {
|
|
70
71
|
const { app, editor } = this
|
|
71
|
-
if (this.running && !this.isMoveMode && app.
|
|
72
|
+
if (this.running && !this.isMoveMode && app.interaction.canHover && !app.interaction.dragging) {
|
|
72
73
|
const find = this.findUI(e)
|
|
73
74
|
editor.hoverTarget = editor.hasItem(find) ? null : find
|
|
74
75
|
} if (this.isMoveMode) {
|
|
@@ -77,14 +78,26 @@ export class EditSelect extends Group implements IEditSelect {
|
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
protected onBeforeDown(e: PointerEvent): void {
|
|
81
|
+
if (e.multiTouch) return
|
|
82
|
+
|
|
80
83
|
const { select } = this.editor.mergeConfig
|
|
81
|
-
if (select === 'press')
|
|
84
|
+
if (select === 'press') {
|
|
85
|
+
if (this.app.config.mobile) {
|
|
86
|
+
this.waitSelect = () => this.checkAndSelect(e)
|
|
87
|
+
} else {
|
|
88
|
+
this.checkAndSelect(e)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
82
91
|
}
|
|
83
92
|
|
|
84
93
|
protected onTap(e: PointerEvent): void {
|
|
94
|
+
if (e.multiTouch) return
|
|
95
|
+
|
|
85
96
|
const { editor } = this
|
|
86
97
|
const { select } = editor.mergeConfig
|
|
98
|
+
|
|
87
99
|
if (select === 'tap') this.checkAndSelect(e)
|
|
100
|
+
else if (this.waitSelect) this.waitSelect()
|
|
88
101
|
|
|
89
102
|
if (this.needRemoveItem) {
|
|
90
103
|
editor.removeItem(this.needRemoveItem)
|
|
@@ -120,6 +133,9 @@ export class EditSelect extends Group implements IEditSelect {
|
|
|
120
133
|
// drag
|
|
121
134
|
|
|
122
135
|
protected onDragStart(e: DragEvent): void {
|
|
136
|
+
if (e.multiTouch) return
|
|
137
|
+
if (this.waitSelect) this.waitSelect()
|
|
138
|
+
|
|
123
139
|
if (this.allowDrag(e)) {
|
|
124
140
|
const { editor } = this
|
|
125
141
|
const { stroke, area } = editor.mergeConfig
|
|
@@ -135,10 +151,8 @@ export class EditSelect extends Group implements IEditSelect {
|
|
|
135
151
|
}
|
|
136
152
|
|
|
137
153
|
protected onDrag(e: DragEvent): void {
|
|
138
|
-
if (
|
|
139
|
-
|
|
140
|
-
return
|
|
141
|
-
}
|
|
154
|
+
if (e.multiTouch) return
|
|
155
|
+
if (this.editor.dragging) return this.onDragEnd(e)
|
|
142
156
|
|
|
143
157
|
if (this.dragging) {
|
|
144
158
|
const { editor } = this
|
|
@@ -171,7 +185,9 @@ export class EditSelect extends Group implements IEditSelect {
|
|
|
171
185
|
}
|
|
172
186
|
}
|
|
173
187
|
|
|
174
|
-
protected onDragEnd(): void {
|
|
188
|
+
protected onDragEnd(e: DragEvent): void {
|
|
189
|
+
if (e.multiTouch) return
|
|
190
|
+
|
|
175
191
|
if (this.dragging) this.originList = null, this.selectArea.visible = false
|
|
176
192
|
}
|
|
177
193
|
|
|
@@ -229,7 +245,7 @@ export class EditSelect extends Group implements IEditSelect {
|
|
|
229
245
|
app.on_(PointerEvent.BEFORE_DOWN, this.onBeforeDown, this),
|
|
230
246
|
app.on_(PointerEvent.TAP, this.onTap, this),
|
|
231
247
|
|
|
232
|
-
app.on_(DragEvent.START, this.onDragStart, this),
|
|
248
|
+
app.on_(DragEvent.START, this.onDragStart, this, true), // 采用捕获事件,需要比EditBox中的dragStart早触发
|
|
233
249
|
app.on_(DragEvent.DRAG, this.onDrag, this),
|
|
234
250
|
app.on_(DragEvent.END, this.onDragEnd, this),
|
|
235
251
|
|
package/src/editor/cursor.ts
CHANGED
|
@@ -12,6 +12,10 @@ export function updateCursor(editor: IEditor, e: IUIEvent): void {
|
|
|
12
12
|
const { editBox } = editor, point = editBox.enterPoint
|
|
13
13
|
if (!point || !editor.editing || !editBox.visible) return
|
|
14
14
|
if (point.name === 'circle') return // 独立旋转按钮
|
|
15
|
+
if (point.pointType === 'button') { // 普通按钮
|
|
16
|
+
if (!point.cursor) point.cursor = 'pointer'
|
|
17
|
+
return
|
|
18
|
+
}
|
|
15
19
|
|
|
16
20
|
let { rotation } = editBox
|
|
17
21
|
const { resizeCursor, rotateCursor, skewCursor, resizeable, rotateable, skewable } = editor.mergeConfig
|
|
@@ -1,31 +1,49 @@
|
|
|
1
|
-
import { IBoundsData, IPointData, IAround, IAlign } from '@leafer-ui/interface'
|
|
2
|
-
import { AroundHelper, PointHelper, Direction9 } from '@leafer-ui/draw'
|
|
1
|
+
import { IBoundsData, IPointData, IAround, IAlign, IUI, ILayoutBoundsData } from '@leafer-ui/interface'
|
|
2
|
+
import { AroundHelper, MathHelper, PointHelper, Direction9 } from '@leafer-ui/draw'
|
|
3
3
|
|
|
4
4
|
import { IEditorScaleEvent, IEditorSkewEvent, IEditorRotateEvent } from '@leafer-in/interface'
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
const { topLeft, top, topRight, right, bottomRight, bottom, bottomLeft, left } = Direction9
|
|
8
8
|
const { toPoint } = AroundHelper
|
|
9
|
+
const { within } = MathHelper
|
|
9
10
|
|
|
10
11
|
export const EditDataHelper = {
|
|
11
12
|
|
|
12
|
-
getScaleData(
|
|
13
|
+
getScaleData(element: IUI, startBounds: ILayoutBoundsData, direction: Direction9, totalMove: IPointData, lockRatio: boolean | 'corner', around: IAround, flipable: boolean, scaleMode: boolean): IEditorScaleEvent {
|
|
13
14
|
let align: IAlign, origin = {} as IPointData, scaleX: number = 1, scaleY: number = 1
|
|
14
|
-
|
|
15
|
+
|
|
16
|
+
const { boxBounds, widthRange, heightRange } = element
|
|
17
|
+
const { width, height } = startBounds
|
|
15
18
|
|
|
16
19
|
if (around) {
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
totalMove.x *= 2
|
|
21
|
+
totalMove.y *= 2
|
|
19
22
|
}
|
|
20
23
|
|
|
24
|
+
|
|
25
|
+
// 获取已经改变的比例
|
|
26
|
+
const originChangedScaleX = element.scaleX / startBounds.scaleX
|
|
27
|
+
const originChangedScaleY = element.scaleY / startBounds.scaleY
|
|
28
|
+
const signX = originChangedScaleX < 0 ? -1 : 1
|
|
29
|
+
const signY = originChangedScaleY < 0 ? -1 : 1
|
|
30
|
+
|
|
31
|
+
const changedScaleX = scaleMode ? originChangedScaleX : signX * boxBounds.width / width
|
|
32
|
+
const changedScaleY = scaleMode ? originChangedScaleY : signY * boxBounds.height / height
|
|
33
|
+
|
|
34
|
+
totalMove.x *= scaleMode ? originChangedScaleX : signX
|
|
35
|
+
totalMove.y *= scaleMode ? originChangedScaleY : signY
|
|
36
|
+
|
|
37
|
+
|
|
21
38
|
// 防止变为0
|
|
22
|
-
if (Math.abs(
|
|
23
|
-
if (Math.abs(
|
|
39
|
+
if (Math.abs(totalMove.x) === width) totalMove.x += 0.1
|
|
40
|
+
if (Math.abs(totalMove.y) === height) totalMove.y += 0.1
|
|
41
|
+
|
|
24
42
|
|
|
25
|
-
const topScale = (-
|
|
26
|
-
const rightScale = (
|
|
27
|
-
const bottomScale = (
|
|
28
|
-
const leftScale = (-
|
|
43
|
+
const topScale = (-totalMove.y + height) / height
|
|
44
|
+
const rightScale = (totalMove.x + width) / width
|
|
45
|
+
const bottomScale = (totalMove.y + height) / height
|
|
46
|
+
const leftScale = (-totalMove.x + width) / width
|
|
29
47
|
|
|
30
48
|
switch (direction) {
|
|
31
49
|
case top:
|
|
@@ -74,7 +92,30 @@ export const EditDataHelper = {
|
|
|
74
92
|
}
|
|
75
93
|
}
|
|
76
94
|
|
|
77
|
-
|
|
95
|
+
|
|
96
|
+
scaleX /= changedScaleX
|
|
97
|
+
scaleY /= changedScaleY
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
if (!flipable) {
|
|
101
|
+
const { worldTransform } = element
|
|
102
|
+
if (scaleX < 0) scaleX = 1 / boxBounds.width / worldTransform.scaleX
|
|
103
|
+
if (scaleY < 0) scaleY = 1 / boxBounds.height / worldTransform.scaleY
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
if (widthRange) {
|
|
108
|
+
const nowWidth = boxBounds.width * element.scaleX
|
|
109
|
+
scaleX = within(nowWidth * scaleX, widthRange) / nowWidth
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (heightRange) {
|
|
113
|
+
const nowHeight = boxBounds.height * element.scaleY
|
|
114
|
+
scaleY = within(nowHeight * scaleY, heightRange) / nowHeight
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
toPoint(around || align, boxBounds, origin)
|
|
78
119
|
|
|
79
120
|
return { origin, scaleX, scaleY, direction, lockRatio, around }
|
|
80
121
|
},
|