@leafer-in/editor 1.7.0 → 1.9.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.
@@ -8,23 +8,26 @@ import { EditDataHelper } from '../helper/EditDataHelper'
8
8
 
9
9
  const cacheCursors: IObject = {}
10
10
 
11
- export function updateCursor(editBox: IEditBox, e: IUIEvent): void {
12
- const { enterPoint: point } = editBox
13
- if (!point || !editBox.editor.editing || !editBox.visible) return
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'
17
17
  return
18
18
  }
19
19
 
20
- let { rotation, flippedX, flippedY } = editBox
20
+ let { rotation } = editBox
21
21
  const { pointType } = point, { resizeCursor, rotateCursor, skewCursor, resizeable, rotateable, skewable } = editBox.mergeConfig
22
22
 
23
23
  let showResize = pointType.includes('resize')
24
- if (showResize && rotateable && (e.metaKey || e.ctrlKey || !resizeable)) showResize = false
24
+ if (showResize && rotateable && (editBox.isHoldRotateKey(e) || !resizeable)) showResize = false
25
25
  const showSkew = skewable && !showResize && (point.name === 'resize-line' || pointType === 'skew')
26
26
 
27
- const cursor = showSkew ? skewCursor : (showResize ? resizeCursor : rotateCursor)
27
+ const cursor = dragging
28
+ ? (skewing ? skewCursor : (resizing ? resizeCursor : rotateCursor))
29
+ : (showSkew ? skewCursor : (showResize ? resizeCursor : rotateCursor))
30
+
28
31
  rotation += (EditDataHelper.getFlipDirection(point.direction, flippedX, flippedY) + 1) * 45
29
32
  rotation = Math.round(MathHelper.formatRotation(rotation, true) / 2) * 2
30
33
 
@@ -40,7 +43,7 @@ export function updateCursor(editBox: IEditBox, e: IUIEvent): void {
40
43
 
41
44
  export function updateMoveCursor(editBox: IEditBox): void {
42
45
  const { moveCursor, moveable } = editBox.mergeConfig
43
- editBox.rect.cursor = moveable ? moveCursor : undefined
46
+ if (editBox.canUse) editBox.rect.cursor = moveable ? moveCursor : undefined
44
47
  }
45
48
 
46
49
 
@@ -16,7 +16,8 @@ export function onTarget(editor: IEditor, oldValue: IUI | IUI[]): void {
16
16
  editor.leafList.reset()
17
17
  }
18
18
 
19
- editor.closeInnerEditor()
19
+ editor.closeInnerEditor(true)
20
+ editor.unloadEditTool()
20
21
 
21
22
  const data = { editor, value: target, oldValue }
22
23
  editor.emitEvent(new EditorEvent(EditorEvent.SELECT, data))
@@ -1,11 +1,11 @@
1
1
  import { IUI, IPointData } from '@leafer-ui/interface'
2
- import { Event } from '@leafer-ui/draw'
2
+ import { Event, isArray } from '@leafer-ui/draw'
3
3
 
4
4
  import { IEditor, IEditorEvent } from '@leafer-in/interface'
5
5
 
6
6
 
7
7
  function toList(value: IUI | IUI[]): IUI[] {
8
- return value ? (value instanceof Array ? value : [value]) : []
8
+ return value ? (isArray(value) ? value : [value]) : []
9
9
  }
10
10
 
11
11
  export class EditorEvent extends Event implements IEditorEvent {
@@ -116,14 +116,18 @@ export const EditDataHelper = {
116
116
 
117
117
  if (dragBounds) {
118
118
  const allowBounds = dragBounds === 'parent' ? target.parent.boxBounds : dragBounds
119
- const localBounds = new Bounds(target.__localBoxBounds)
120
- localBounds.scaleOf(target.getLocalPointByInner(origin), scaleX, scaleY)
121
-
122
- if (!BoundsHelper.includes(allowBounds, localBounds)) {
123
- const realBounds = localBounds.getIntersect(allowBounds)
124
- const fitScaleX = realBounds.width / localBounds.width, fitScaleY = realBounds.height / localBounds.height
125
- if (useScaleX) scaleX *= fitScaleX
126
- if (useScaleY) scaleY *= fitScaleY // 后续需优化带旋转的场景
119
+ const childBounds = new Bounds(target.__localBoxBounds)
120
+
121
+ if (BoundsHelper.includes(new Bounds(allowBounds).spread(0.1), childBounds)) {
122
+
123
+ childBounds.scaleOf(target.getLocalPointByInner(origin), scaleX, scaleY)
124
+
125
+ if (!BoundsHelper.includes(allowBounds, childBounds)) {
126
+ const realBounds = childBounds.getIntersect(allowBounds)
127
+ const fitScaleX = realBounds.width / childBounds.width, fitScaleY = realBounds.height / childBounds.height
128
+ if (useScaleX) scaleX *= fitScaleX
129
+ if (useScaleY) scaleY *= fitScaleY // 后续需优化带旋转的场景
130
+ }
127
131
  }
128
132
  }
129
133
 
package/src/index.ts CHANGED
@@ -47,7 +47,7 @@ Creator.editor = function (options?: IEditorConfig, app?: IApp): IEditor {
47
47
  Box.addAttr('textBox', false, dataType)
48
48
 
49
49
  UI.addAttr('editConfig', undefined, dataType)
50
- UI.addAttr('editOuter', (ui: UI) => ui.__.__isLinePath ? 'LineEditTool' : 'EditTool', dataType)
50
+ UI.addAttr('editOuter', (ui: UI) => { ui.updateLayout(); return ui.__.__isLinePath ? 'LineEditTool' : 'EditTool' }, dataType) // fix: Line 需要更新布局才能精准确定
51
51
 
52
52
  UI.addAttr('editInner', 'PathEditor', dataType)
53
53
  Group.addAttr('editInner', '', dataType) // 必须设为空
@@ -1,5 +1,5 @@
1
- import { IEvent, IPointData, IAlign, IAxis, IFunction, IMatrix } from '@leafer-ui/interface'
2
- import { MathHelper, Matrix, LeafHelper } from '@leafer-ui/draw'
1
+ import { IEvent, IPointData, IAlign, IAxis, IFunction, IMatrix, IUI } from '@leafer-ui/interface'
2
+ import { MathHelper, Matrix, LeafHelper, AroundHelper, isObject, isNumber, isUndefined } from '@leafer-ui/draw'
3
3
  import { DragEvent, RotateEvent, ZoomEvent, MoveEvent } from '@leafer-ui/core'
4
4
 
5
5
  import { IEditBox, IEditPoint, IEditTool, IEditorScaleEvent, ISimulateElement, IEditorMoveEvent, IEditorRotateEvent, IEditorSkewEvent } from '@leafer-in/interface'
@@ -23,17 +23,18 @@ export class TransformTool implements ITransformTool { // Editor use
23
23
 
24
24
  public onMove(e: DragEvent | MoveEvent): void {
25
25
 
26
- const { target, mergeConfig, dragStartData } = this.editBox
26
+ const { target, mergeConfig, dragStartData, app } = this.editBox
27
27
 
28
- if (e instanceof MoveEvent) {
28
+ let move: IPointData, { dragLimitAnimate } = mergeConfig
29
+ if (isUndefined(dragLimitAnimate)) dragLimitAnimate = app && app.config.pointer.dragLimitAnimate
29
30
 
30
- if (e.moveType !== 'drag') {
31
- const { moveable, resizeable } = mergeConfig
32
- const move = e.getLocalMove(target)
31
+ const isMoveEnd = e.type === DragEvent.END || e.type === DragEvent.END
32
+ const checkLimitMove = !dragLimitAnimate || isMoveEnd
33
33
 
34
- if (moveable === 'move') e.stop(), this.move(move.x, move.y)
35
- else if (resizeable === 'zoom') e.stop()
36
- }
34
+ if (e instanceof MoveEvent) {
35
+
36
+ move = e.getLocalMove(target)
37
+ if (checkLimitMove) DragEvent.limitMove(target, move)
37
38
 
38
39
  } else {
39
40
 
@@ -44,19 +45,23 @@ export class TransformTool implements ITransformTool { // Editor use
44
45
  else total.x = 0
45
46
  }
46
47
 
47
- this.move(DragEvent.getValidMove(target, dragStartData.point, total))
48
+ move = DragEvent.getValidMove(target, dragStartData.point, total, checkLimitMove)
48
49
 
49
50
  }
51
+
52
+ if (dragLimitAnimate && isMoveEnd) LeafHelper.animateMove(this as unknown as IUI, move, isNumber(dragLimitAnimate) ? dragLimitAnimate : 0.3) // 是否进行动画
53
+ else this.move(move)
54
+
50
55
  }
51
56
 
52
57
  public onScale(e: DragEvent | ZoomEvent): void {
53
58
 
54
59
  const { target, mergeConfig, single, dragStartData } = this.editBox
55
- let { around, lockRatio, resizeable, flipable, editSize } = mergeConfig
60
+ let { around, lockRatio, flipable, editSize } = mergeConfig
56
61
 
57
62
  if (e instanceof ZoomEvent) {
58
63
 
59
- if (resizeable === 'zoom') e.stop(), this.scaleOf(target.getBoxPoint(e), e.scale, e.scale)
64
+ this.scaleOf(target.getBoxPoint(e), e.scale, e.scale)
60
65
 
61
66
  } else {
62
67
 
@@ -78,31 +83,24 @@ export class TransformTool implements ITransformTool { // Editor use
78
83
  public onRotate(e: DragEvent | RotateEvent): void {
79
84
 
80
85
  const { target, mergeConfig, dragStartData } = this.editBox
81
- const { skewable, rotateable, around, rotateGap } = mergeConfig
82
- const { direction, name } = e.current as IEditPoint
83
-
84
- if (skewable && name === 'resize-line') return this.onSkew(e as DragEvent)
86
+ const { around, rotateAround, rotateGap } = mergeConfig
87
+ const { direction } = e.current as IEditPoint
85
88
 
86
89
  let origin: IPointData, rotation: number
87
90
 
88
91
  if (e instanceof RotateEvent) {
89
92
 
90
- if (rotateable === 'rotate') e.stop(), rotation = e.rotation, origin = target.getBoxPoint(e)
91
- else return
92
-
93
- if (target.scaleX * target.scaleY < 0) rotation = -rotation // flippedOne
93
+ rotation = e.rotation
94
+ origin = rotateAround ? AroundHelper.getPoint(rotateAround, target.boxBounds) : target.getBoxPoint(e)
94
95
 
95
96
  } else {
96
97
 
97
- const data = EditDataHelper.getRotateData(target, direction, e, dragStartData, e.shiftKey ? null : (target.around || target.origin || around || 'center'))
98
- rotation = data.rotation
98
+ const data = EditDataHelper.getRotateData(target, direction, e, dragStartData, e.shiftKey ? null : (rotateAround || target.around || target.origin || around || 'center'))
99
+ rotation = dragStartData.rotation + data.rotation - target.rotation
99
100
  origin = data.origin
100
101
 
101
102
  }
102
103
 
103
- if (target.scaleX * target.scaleY < 0) rotation = -rotation // flippedOne
104
- if (e instanceof DragEvent) rotation = dragStartData.rotation + rotation - target.rotation
105
-
106
104
  rotation = MathHelper.float(MathHelper.getGapRotation(rotation, rotateGap, target.rotation), 2)
107
105
  if (!rotation) return
108
106
 
@@ -125,13 +123,13 @@ export class TransformTool implements ITransformTool { // Editor use
125
123
 
126
124
  public move(x: number | IPointData, y = 0): void {
127
125
  if (!this.checkTransform('moveable')) return
128
- if (typeof x === 'object') y = x.y, x = x.x
126
+ if (isObject(x)) y = x.y, x = x.x
129
127
 
130
128
  const { target, mergeConfig, single, editor } = this.editBox
131
129
  const { beforeMove } = mergeConfig
132
130
  if (beforeMove) {
133
131
  const check = beforeMove({ target, x, y })
134
- if (typeof check === 'object') x = check.x, y = check.y
132
+ if (isObject(check)) x = check.x, y = check.y
135
133
  else if (check === false) return
136
134
  }
137
135
 
@@ -172,7 +170,7 @@ export class TransformTool implements ITransformTool { // Editor use
172
170
  const { beforeScale } = mergeConfig
173
171
  if (beforeScale) {
174
172
  const check = beforeScale({ target, origin, scaleX, scaleY })
175
- if (typeof check === 'object') scaleX = check.scaleX, scaleY = check.scaleY
173
+ if (isObject(check)) scaleX = check.scaleX, scaleY = check.scaleY
176
174
  else if (check === false) return
177
175
  }
178
176
 
@@ -209,7 +207,7 @@ export class TransformTool implements ITransformTool { // Editor use
209
207
  const { beforeRotate } = mergeConfig
210
208
  if (beforeRotate) {
211
209
  const check = beforeRotate({ target, origin, rotation })
212
- if (typeof check === 'number') rotation = check
210
+ if (isNumber(check)) rotation = check
213
211
  else if (check === false) return
214
212
  }
215
213
 
@@ -231,7 +229,7 @@ export class TransformTool implements ITransformTool { // Editor use
231
229
  const { beforeSkew } = mergeConfig
232
230
  if (beforeSkew) {
233
231
  const check = beforeSkew({ target, origin, skewX, skewY })
234
- if (typeof check === 'object') skewX = check.skewX, skewY = check.skewY
232
+ if (isObject(check)) skewX = check.skewX, skewY = check.skewY
235
233
  else if (check === false) return
236
234
  }
237
235
 
package/types/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { IBounds, ILeafList, IUI, IFunction, IEventListenerId, ILeaf, IPointerEvent, ILeaferCanvas, IRenderOptions, IGroup, IObject, IGroupInputData, IEditSize, IPointData, IAlign, IAxis, IMatrix, IApp, IBox, IEditorDragStartData, IEditorConfig as IEditorConfig$1, ITransformTool, IBoundsData, IBoxInputData, IKeyEvent, IRect, IRectInputData, IMatrixData, IDragEvent, IAround, IEvent, ILayoutBoundsData } from '@leafer-ui/interface';
2
- import { Group, UI, Direction9, Event, Box } from '@leafer-ui/draw';
1
+ import { IBounds, ILeafList, IUI, IFunction, IEventListenerId, ILeaf, IPointerEvent, ILeaferCanvas, IRenderOptions, IGroup, IObject, IGroupInputData, IEditSize, IPointData, IAlign, IAxis, IMatrix, IApp, IBox, IEditorDragStartData, IEditorConfig as IEditorConfig$1, ITransformTool, IBoundsData, IBoxInputData, IUIEvent, IKeyEvent, IRect, IRectInputData, IMatrixData, IDragEvent, IAround, IEvent, ILayoutBoundsData } from '@leafer-ui/interface';
2
+ import { Group, UI, Direction9, Box, Event } from '@leafer-ui/draw';
3
3
  import { PointerEvent, DragEvent, MoveEvent, ZoomEvent, RotateEvent, KeyEvent } from '@leafer-ui/core';
4
- import { IEditSelect, IEditor, IStroker, ISelectArea, IEditorConfig, IEditPoint, ISimulateElement, IEditBox, IEditTool, IInnerEditor, IEditorScaleEvent, IEditorEvent, IEditPointType, IEditPointInputData, IEditorMoveEvent, IEditorRotateEvent, IEditorSkewEvent, IEditorGroupEvent, IInnerEditorEvent, IInnerEditorMode, IUI as IUI$1, IDragEvent as IDragEvent$1, IPointData as IPointData$1, IPathCommandData, IFromToData, IAround as IAround$1 } from '@leafer-in/interface';
4
+ import { IEditSelect, IEditor, IStroker, ISelectArea, IEditorConfig, IEditPoint, ISimulateElement, IEditBox, IEditTool, IInnerEditor, IEditorScaleEvent, IEditPointType, IEditPointInputData, IEditorEvent, IEditorMoveEvent, IEditorRotateEvent, IEditorSkewEvent, IEditorGroupEvent, IInnerEditorEvent, IInnerEditorMode, IUI as IUI$1, IDragEvent as IDragEvent$1, IPointData as IPointData$1, IPathCommandData, IFromToData, IAround as IAround$1 } from '@leafer-in/interface';
5
5
 
6
6
  declare class EditSelect extends Group implements IEditSelect {
7
7
  editor: IEditor;
@@ -34,6 +34,7 @@ declare class EditSelect extends Group implements IEditSelect {
34
34
  findDeepOne(e: PointerEvent): IUI;
35
35
  findUI(e: PointerEvent): IUI;
36
36
  isMultipleSelect(e: IPointerEvent): boolean;
37
+ isHoldMultipleSelectKey(e: IPointerEvent): boolean;
37
38
  protected __listenEvents(): void;
38
39
  protected __removeListenEvents(): void;
39
40
  destroy(): void;
@@ -63,9 +64,13 @@ declare class Editor extends Group implements IEditor {
63
64
  resizeDirection?: Direction9;
64
65
  get multiple(): boolean;
65
66
  get single(): boolean;
67
+ get dragPoint(): IEditPoint;
66
68
  get dragging(): boolean;
69
+ get gesturing(): boolean;
67
70
  get moving(): boolean;
68
- get dragPoint(): IEditPoint;
71
+ get resizing(): boolean;
72
+ get rotating(): boolean;
73
+ get skewing(): boolean;
69
74
  get element(): ISimulateElement;
70
75
  simulateTarget: ISimulateElement;
71
76
  editBox: IEditBox;
@@ -87,6 +92,7 @@ declare class Editor extends Group implements IEditor {
87
92
  update(): void;
88
93
  updateEditBox(): void;
89
94
  updateEditTool(): void;
95
+ unloadEditTool(): void;
90
96
  getEditSize(_ui: IUI): IEditSize;
91
97
  onMove(_e: DragEvent | MoveEvent): void;
92
98
  onScale(_e: DragEvent | ZoomEvent): void;
@@ -108,8 +114,8 @@ declare class Editor extends Group implements IEditor {
108
114
  checkOpenedGroups(): void;
109
115
  checkDeepSelect(): void;
110
116
  emitGroupEvent(type: string, group?: IGroup): void;
111
- openInnerEditor(target?: IUI, select?: boolean): void;
112
- closeInnerEditor(): void;
117
+ openInnerEditor(target?: IUI, nameOrSelect?: string | boolean, select?: boolean): void;
118
+ closeInnerEditor(onlyInnerEditor?: boolean): void;
113
119
  emitInnerEvent(type: string): void;
114
120
  lock(): void;
115
121
  unlock(): void;
@@ -122,27 +128,14 @@ declare class Editor extends Group implements IEditor {
122
128
  destroy(): void;
123
129
  }
124
130
 
125
- declare class EditorEvent extends Event implements IEditorEvent {
126
- static BEFORE_SELECT: string;
127
- static SELECT: string;
128
- static AFTER_SELECT: string;
129
- static BEFORE_HOVER: string;
130
- static HOVER: string;
131
- readonly target: IUI;
132
- readonly editor: IEditor;
133
- readonly value: IUI | IUI[];
134
- readonly oldValue: IUI | IUI[];
135
- get list(): IUI[];
136
- get oldList(): IUI[];
137
- readonly worldOrigin: IPointData;
138
- readonly origin: IPointData;
139
- constructor(type: string, data?: IEditorEvent);
140
- }
141
-
142
131
  declare class EditBox extends Group implements IEditBox {
143
132
  editor: IEditor;
144
133
  dragging: boolean;
134
+ gesturing: boolean;
145
135
  moving: boolean;
136
+ resizing: boolean;
137
+ rotating: boolean;
138
+ skewing: boolean;
146
139
  view: IGroup;
147
140
  rect: IBox;
148
141
  circle: IEditPoint;
@@ -167,23 +160,29 @@ declare class EditBox extends Group implements IEditBox {
167
160
  get flippedX(): boolean;
168
161
  get flippedY(): boolean;
169
162
  get flippedOne(): boolean;
163
+ get canUse(): boolean;
164
+ get canGesture(): boolean;
170
165
  protected __eventIds: IEventListenerId[];
171
166
  constructor(editor: IEditor);
172
167
  create(): void;
173
168
  load(): void;
174
169
  update(): void;
170
+ unload(): void;
175
171
  updateBounds(bounds: IBoundsData): void;
176
172
  protected layoutCircle(): void;
177
173
  protected layoutButtons(): void;
178
174
  protected setButtonPosition(buttons: IUI, direction: number, buttonsMargin: number, useMiddlePoint: boolean): void;
179
- unload(): void;
180
175
  getPointStyle(userStyle?: IBoxInputData): IBoxInputData;
181
176
  getPointsStyle(): IBoxInputData[];
182
177
  getMiddlePointsStyle(): IBoxInputData[];
183
- protected onSelect(e: EditorEvent): void;
184
178
  protected onDragStart(e: DragEvent): void;
185
179
  protected onDragEnd(e: DragEvent): void;
186
180
  protected onDrag(e: DragEvent): void;
181
+ protected resetDoing(): void;
182
+ onMove(e: MoveEvent): void;
183
+ onScale(e: ZoomEvent): void;
184
+ onRotate(e: RotateEvent): void;
185
+ isHoldRotateKey(e: IUIEvent): boolean;
187
186
  protected onKey(e: KeyEvent): void;
188
187
  onArrow(e: IKeyEvent): void;
189
188
  protected onDoubleTap(e: PointerEvent): void;
@@ -213,12 +212,29 @@ declare class Stroker extends UI implements IStroker {
213
212
  target: IUI | IUI[];
214
213
  list: IUI[];
215
214
  constructor();
216
- setTarget(target: IUI | IUI[], style: IRectInputData): void;
217
- update(): void;
215
+ setTarget(target: IUI | IUI[], style?: IRectInputData): void;
216
+ update(style?: IRectInputData): void;
218
217
  __draw(canvas: ILeaferCanvas, options: IRenderOptions): void;
219
218
  destroy(): void;
220
219
  }
221
220
 
221
+ declare class EditorEvent extends Event implements IEditorEvent {
222
+ static BEFORE_SELECT: string;
223
+ static SELECT: string;
224
+ static AFTER_SELECT: string;
225
+ static BEFORE_HOVER: string;
226
+ static HOVER: string;
227
+ readonly target: IUI;
228
+ readonly editor: IEditor;
229
+ readonly value: IUI | IUI[];
230
+ readonly oldValue: IUI | IUI[];
231
+ get list(): IUI[];
232
+ get oldList(): IUI[];
233
+ readonly worldOrigin: IPointData;
234
+ readonly origin: IPointData;
235
+ constructor(type: string, data?: IEditorEvent);
236
+ }
237
+
222
238
  declare class EditorMoveEvent extends EditorEvent implements IEditorMoveEvent {
223
239
  static BEFORE_MOVE: string;
224
240
  static MOVE: string;