@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/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
- const total = { x: e.totalX, y: e.totalY }
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
- if (this.mergeConfig.resizeable === 'zoom') {
172
- e.stop()
173
- this.scaleOf(element.getInnerPoint(e), e.scale, e.scale)
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
- let { around, lockRatio } = this.mergeConfig
194
+
179
195
  if (e.shiftKey || element.lockRatio) lockRatio = true
180
196
 
181
- const data = EditDataHelper.getScaleData(element.boxBounds, direction, e.getInnerMove(element), lockRatio, EditDataHelper.getAround(around, e.altKey))
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
- if (this.mergeConfig.rotateable === 'rotate') {
204
- e.stop()
205
- rotation = e.rotation, origin = element.getInnerPoint(e)
206
- } else return
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 worldOrigin = element.getWorldPoint(data.origin)
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
- public scaleOf(origin: IPointData | IAlign, scaleX: number, scaleY = scaleX, _resize?: boolean): void {
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 = 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
-
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
- public rotateOf(origin: IPointData | IAlign, rotation: number): void {
282
- if (!this.mergeConfig.rotateable || this.element.locked) return
290
+ override flip(axis: IAxis): void {
291
+ if (this.element.locked) return
283
292
 
284
293
  const { element } = this
285
- const worldOrigin = element.getWorldPoint(LeafHelper.getInnerOrigin(element, origin))
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
- let transform: Matrix
298
+ this.editTool.onScale(event)
299
+ this.emitEvent(event)
300
+ }
289
301
 
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
- }
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
- public skewOf(origin: IPointData | IAlign, skewX: number, skewY = 0, _resize?: boolean): void {
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 = element.getWorldPoint(LeafHelper.getInnerOrigin(element, origin))
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
- let transform: Matrix
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
- const event = new EditorSkewEvent(EditorSkewEvent.SKEW, {
317
- target: element, editor: this, skewX, skewY, transform, worldOrigin
318
- })
327
+ protected getWorldOrigin(origin: IPointData | IAlign): IPointData {
328
+ return this.element.getWorldPoint(LeafHelper.getInnerOrigin(this.element, origin))
329
+ }
319
330
 
320
- this.editTool.onSkew(event)
321
- this.emitEvent(event)
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
@@ -33,6 +33,7 @@ export const config: IEditorConfig = {
33
33
 
34
34
  moveable: true,
35
35
  resizeable: true,
36
+ flipable: true,
36
37
  rotateable: true,
37
38
  skewable: true
38
39
  }
@@ -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, RotateEvent, ZoomEvent } from '@leafer-ui/core'
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
- const buttonVisible = showPoints && (circle.visible || this.buttons.children.length > 1)
161
- this.buttons.visible = buttonVisible
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 layoutButtons(): void {
167
- const { buttons, resizePoints } = this
168
- const { buttonsDirection, buttonsFixed, buttonsMargin, middlePoint } = this.editor.mergeConfig
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
- const point = resizePoints[direction * 2 + 1] // 4 map 8 direction
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 = index % 2 // left / right origin direction
182
- const margin = (buttonsMargin + (useWidth ? ((middlePoint ? point.width : 0) + buttons.boxBounds.width) : ((middlePoint ? point.height : 0) + buttons.boxBounds.height)) / 2) * sign
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)
@@ -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 __eventIds: IEventListenerId[] = []
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.config.pointer.hover && !app.interaction.dragging) {
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') this.checkAndSelect(e)
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 (this.editor.dragging) {
139
- this.onDragEnd()
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
 
@@ -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(bounds: IBoundsData, direction: Direction9, pointMove: IPointData, lockRatio: boolean | 'corner', around: IAround): IEditorScaleEvent {
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
- const { width, height } = bounds
15
+
16
+ const { boxBounds, widthRange, heightRange } = element
17
+ const { width, height } = startBounds
15
18
 
16
19
  if (around) {
17
- pointMove.x *= 2
18
- pointMove.y *= 2
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(pointMove.x) === width) pointMove.x += 0.1
23
- if (Math.abs(pointMove.y) === height) pointMove.y += 0.1
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 = (-pointMove.y + height) / height
26
- const rightScale = (pointMove.x + width) / width
27
- const bottomScale = (pointMove.y + height) / height
28
- const leftScale = (-pointMove.x + width) / width
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
- toPoint(around || align, bounds, origin)
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
  },