@leafer-in/editor 1.5.3 → 1.6.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 +130 -80
- package/dist/editor.cjs.map +1 -1
- package/dist/editor.esm.js +131 -81
- package/dist/editor.esm.js.map +1 -1
- package/dist/editor.esm.min.js +1 -1
- package/dist/editor.esm.min.js.map +1 -1
- package/dist/editor.js +130 -80
- package/dist/editor.js.map +1 -1
- 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 +5 -5
- package/src/Editor.ts +34 -27
- package/src/decorator/data.ts +25 -2
- package/src/display/EditBox.ts +26 -19
- package/src/display/EditMask.ts +19 -10
- package/src/display/EditSelect.ts +1 -1
- package/src/display/SelectArea.ts +2 -1
- package/src/display/Stroker.ts +9 -8
- package/src/helper/EditDataHelper.ts +12 -9
- package/src/tool/EditTool.ts +7 -18
- package/types/index.d.ts +9 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leafer-in/editor",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "@leafer-in/editor",
|
|
5
5
|
"author": "Chao (Leafer) Wan",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
"leaferjs"
|
|
35
35
|
],
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"@leafer-ui/core": "^1.
|
|
38
|
-
"@leafer-in/resize": "^1.
|
|
39
|
-
"@leafer-ui/interface": "^1.
|
|
40
|
-
"@leafer-in/interface": "^1.
|
|
37
|
+
"@leafer-ui/core": "^1.6.0",
|
|
38
|
+
"@leafer-in/resize": "^1.6.0",
|
|
39
|
+
"@leafer-ui/interface": "^1.6.0",
|
|
40
|
+
"@leafer-in/interface": "^1.6.0"
|
|
41
41
|
}
|
|
42
42
|
}
|
package/src/Editor.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { IGroupInputData, IUI, IEventListenerId, IPointData, ILeafList, IEditSize, IGroup, IObject, IAlign, IAxis, IFunction, IMatrix } from '@leafer-ui/interface'
|
|
2
|
-
import { Group, DataHelper, MathHelper, LeafList, Matrix, RenderEvent, LeafHelper, Direction9
|
|
1
|
+
import { IGroupInputData, IUI, IEventListenerId, IPointData, ILeafList, IEditSize, IGroup, IObject, IAlign, IAxis, IFunction, IMatrix, IApp } from '@leafer-ui/interface'
|
|
2
|
+
import { Group, DataHelper, MathHelper, LeafList, Matrix, RenderEvent, LeafHelper, Direction9 } from '@leafer-ui/draw'
|
|
3
3
|
import { DragEvent, RotateEvent, KeyEvent, ZoomEvent, MoveEvent, Plugin } from '@leafer-ui/core'
|
|
4
4
|
|
|
5
5
|
import { IEditBox, IEditPoint, IEditor, IEditorConfig, IEditTool, IEditorScaleEvent, IInnerEditor, ISimulateElement, IEditorMoveEvent, IEditorRotateEvent, IEditorSkewEvent } from '@leafer-in/interface'
|
|
@@ -16,7 +16,7 @@ import { EditMask } from './display/EditMask'
|
|
|
16
16
|
import { config } from './config'
|
|
17
17
|
|
|
18
18
|
import { onTarget, onHover } from './editor/target'
|
|
19
|
-
import { targetAttr } from './decorator/data'
|
|
19
|
+
import { targetAttr, mergeConfigAttr } from './decorator/data'
|
|
20
20
|
import { EditorHelper } from './helper/EditorHelper'
|
|
21
21
|
import { EditDataHelper } from './helper/EditDataHelper'
|
|
22
22
|
import { simulate } from './editor/simulate'
|
|
@@ -29,21 +29,11 @@ import { SimulateElement } from './display/SimulateElement'
|
|
|
29
29
|
|
|
30
30
|
export class Editor extends Group implements IEditor {
|
|
31
31
|
|
|
32
|
-
public config
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (dragPoint) {
|
|
38
|
-
if (dragPoint.editConfig) Object.assign(mergeConfig, dragPoint.editConfig)
|
|
39
|
-
if (mergeConfig.editSize === 'font-size') mergeConfig.lockRatio = true // 强制锁定比例
|
|
40
|
-
if (dragPoint.pointType === 'resize-rotate') {
|
|
41
|
-
mergeConfig.around || (mergeConfig.around = 'center')
|
|
42
|
-
isNull(mergeConfig.lockRatio) && (mergeConfig.lockRatio = true)
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return mergeConfig
|
|
46
|
-
}
|
|
32
|
+
public config: IEditorConfig
|
|
33
|
+
|
|
34
|
+
@mergeConfigAttr()
|
|
35
|
+
readonly mergeConfig: IEditorConfig
|
|
36
|
+
readonly mergedConfig: IEditorConfig
|
|
47
37
|
|
|
48
38
|
@targetAttr(onHover)
|
|
49
39
|
public hoverTarget?: IUI
|
|
@@ -88,12 +78,16 @@ export class Editor extends Group implements IEditor {
|
|
|
88
78
|
public selector: EditSelect = new EditSelect(this)
|
|
89
79
|
public editMask: EditMask = new EditMask(this)
|
|
90
80
|
|
|
81
|
+
public targetChanged: boolean
|
|
91
82
|
public targetEventIds: IEventListenerId[] = []
|
|
92
83
|
|
|
93
84
|
|
|
94
85
|
constructor(userConfig?: IEditorConfig, data?: IGroupInputData) {
|
|
95
86
|
super(data)
|
|
96
|
-
|
|
87
|
+
let mergedConfig: IEditorConfig = DataHelper.clone(config)
|
|
88
|
+
if (userConfig) mergedConfig = DataHelper.default(userConfig, mergedConfig)
|
|
89
|
+
this.mergedConfig = this.config = mergedConfig
|
|
90
|
+
|
|
97
91
|
this.addMany(this.editMask, this.selector, this.editBox)
|
|
98
92
|
if (!Plugin.has('resize')) this.config.editSize = 'scale'
|
|
99
93
|
}
|
|
@@ -489,8 +483,7 @@ export class Editor extends Group implements IEditor {
|
|
|
489
483
|
}
|
|
490
484
|
|
|
491
485
|
public emitInnerEvent(type: string): void {
|
|
492
|
-
const { innerEditor } = this
|
|
493
|
-
const { editTarget } = innerEditor
|
|
486
|
+
const { innerEditor } = this, { editTarget } = innerEditor
|
|
494
487
|
const event = new InnerEditorEvent(type, { editTarget, innerEditor })
|
|
495
488
|
this.emitEvent(event)
|
|
496
489
|
editTarget.emitEvent(event)
|
|
@@ -524,28 +517,42 @@ export class Editor extends Group implements IEditor {
|
|
|
524
517
|
}
|
|
525
518
|
}
|
|
526
519
|
|
|
520
|
+
protected onAppRenderStart(app: IApp): void {
|
|
521
|
+
if (this.targetChanged = app.children.some(leafer => leafer !== this.leafer && leafer.renderer.changed)) this.editBox.forceRender()
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
protected onRenderStart(): void {
|
|
525
|
+
if (this.targetChanged) this.update()
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
protected onKey(e: KeyEvent): void {
|
|
529
|
+
updateCursor(this, e)
|
|
530
|
+
}
|
|
531
|
+
|
|
527
532
|
// event
|
|
528
533
|
|
|
529
534
|
public listenTargetEvents(): void {
|
|
530
535
|
if (!this.targetEventIds.length) {
|
|
531
|
-
const { app, leafer } = this
|
|
536
|
+
const { app, leafer, editBox, editMask } = this
|
|
532
537
|
this.targetEventIds = [
|
|
533
|
-
leafer.on_(RenderEvent.START, this.
|
|
534
|
-
app.on_(RenderEvent.CHILD_START, this.
|
|
538
|
+
leafer.on_(RenderEvent.START, this.onRenderStart, this),
|
|
539
|
+
app.on_(RenderEvent.CHILD_START, this.onAppRenderStart, this),
|
|
535
540
|
app.on_(MoveEvent.BEFORE_MOVE, this.onMove, this, true),
|
|
536
541
|
app.on_(ZoomEvent.BEFORE_ZOOM, this.onScale, this, true),
|
|
537
542
|
app.on_(RotateEvent.BEFORE_ROTATE, this.onRotate, this, true),
|
|
538
|
-
app.on_([KeyEvent.HOLD, KeyEvent.UP],
|
|
539
|
-
app.on_(KeyEvent.DOWN,
|
|
543
|
+
app.on_([KeyEvent.HOLD, KeyEvent.UP], this.onKey, this),
|
|
544
|
+
app.on_(KeyEvent.DOWN, editBox.onArrow, editBox)
|
|
540
545
|
]
|
|
546
|
+
if (editMask.visible) editMask.forceRender()
|
|
541
547
|
}
|
|
542
548
|
}
|
|
543
549
|
|
|
544
550
|
public removeTargetEvents(): void {
|
|
545
|
-
const { targetEventIds } = this
|
|
551
|
+
const { targetEventIds, editMask } = this
|
|
546
552
|
if (targetEventIds.length) {
|
|
547
553
|
this.off_(targetEventIds)
|
|
548
554
|
targetEventIds.length = 0
|
|
555
|
+
if (editMask.visible) editMask.forceRender()
|
|
549
556
|
}
|
|
550
557
|
}
|
|
551
558
|
|
package/src/decorator/data.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IFunction, ILeaf, IObject, IUI, } from '@leafer-ui/interface'
|
|
2
2
|
import { IEditor } from '@leafer-in/interface'
|
|
3
|
-
import { defineKey } from '@leafer-ui/draw'
|
|
3
|
+
import { defineKey, isNull } from '@leafer-ui/draw'
|
|
4
4
|
|
|
5
5
|
import { EditorEvent } from '../event/EditorEvent'
|
|
6
6
|
|
|
@@ -37,4 +37,27 @@ export function targetAttr(fn: IFunction) {
|
|
|
37
37
|
}
|
|
38
38
|
} as ThisType<ILeaf>)
|
|
39
39
|
}
|
|
40
|
-
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
export function mergeConfigAttr() {
|
|
44
|
+
return (target: IEditor, key: string) => {
|
|
45
|
+
defineKey(target, key, {
|
|
46
|
+
get() {
|
|
47
|
+
const { config, element, dragPoint } = this, mergeConfig = { ...config } // 实时合并,后期可优化
|
|
48
|
+
if (element && element.editConfig) Object.assign(mergeConfig, element.editConfig)
|
|
49
|
+
if (dragPoint) {
|
|
50
|
+
if (dragPoint.editConfig) Object.assign(mergeConfig, dragPoint.editConfig)
|
|
51
|
+
if (mergeConfig.editSize === 'font-size') mergeConfig.lockRatio = true // 强制锁定比例
|
|
52
|
+
if (dragPoint.pointType === 'resize-rotate') {
|
|
53
|
+
mergeConfig.around || (mergeConfig.around = 'center')
|
|
54
|
+
isNull(mergeConfig.lockRatio) && (mergeConfig.lockRatio = true)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return (this as IObject).mergedConfig = mergeConfig
|
|
58
|
+
}
|
|
59
|
+
} as ThisType<IEditor>)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
package/src/display/EditBox.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IRect, IEventListenerId, IBoundsData, IPointData, IKeyEvent, IGroup, IBox, IBoxInputData, IAlign, IUI, IEditorConfig, IEditorDragStartData } from '@leafer-ui/interface'
|
|
2
|
-
import { Group, Box, Text, AroundHelper, Direction9 } from '@leafer-ui/draw'
|
|
2
|
+
import { Group, Box, Text, AroundHelper, Direction9, ResizeEvent } from '@leafer-ui/draw'
|
|
3
3
|
import { DragEvent, PointerEvent } from '@leafer-ui/core'
|
|
4
4
|
|
|
5
5
|
import { IEditBox, IEditor, IEditPoint, IEditPointType } from '@leafer-in/interface'
|
|
@@ -22,7 +22,7 @@ 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
|
-
public buttons: IGroup = new Group({ around: 'center', hitSelf: false })
|
|
25
|
+
public buttons: IGroup = new Group({ around: 'center', hitSelf: false, visible: 0 })
|
|
26
26
|
|
|
27
27
|
public resizePoints: IEditPoint[] = [] // topLeft, top, topRight, right, bottomRight, bottom, bottomLeft, left
|
|
28
28
|
public rotatePoints: IEditPoint[] = [] // topLeft, top, topRight, right, bottomRight, bottom, bottomLeft, left
|
|
@@ -108,14 +108,15 @@ export class EditBox extends Group implements IEditBox {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
public update(bounds: IBoundsData): void {
|
|
111
|
-
const {
|
|
112
|
-
const {
|
|
111
|
+
const { rect, circle, buttons, resizePoints, rotatePoints, resizeLines, editor } = this
|
|
112
|
+
const { mergeConfig, element, multiple, editMask } = editor
|
|
113
|
+
const { middlePoint, resizeable, rotateable, hideOnSmall, editBox, mask } = mergeConfig
|
|
114
|
+
|
|
113
115
|
this.visible = !element.locked
|
|
116
|
+
editMask.visible = mask ? true : 0
|
|
114
117
|
|
|
115
118
|
if (this.view.worldOpacity) {
|
|
116
119
|
const { width, height } = bounds
|
|
117
|
-
const { rect, circle, buttons, resizePoints, rotatePoints, resizeLines } = this
|
|
118
|
-
|
|
119
120
|
const smallSize = typeof hideOnSmall === 'number' ? hideOnSmall : 10
|
|
120
121
|
const showPoints = editBox && !(hideOnSmall && width < smallSize && height < smallSize)
|
|
121
122
|
|
|
@@ -160,9 +161,9 @@ export class EditBox extends Group implements IEditBox {
|
|
|
160
161
|
rect.set({ ...bounds, visible: multiple ? true : editBox })
|
|
161
162
|
|
|
162
163
|
// buttons
|
|
163
|
-
buttons.visible = showPoints && buttons.children.length > 0
|
|
164
|
+
buttons.visible = showPoints && buttons.children.length > 0 || 0
|
|
164
165
|
if (buttons.visible) this.layoutButtons(mergeConfig)
|
|
165
|
-
}
|
|
166
|
+
} else rect.set(bounds) // 需要更新大小
|
|
166
167
|
}
|
|
167
168
|
|
|
168
169
|
protected layoutCircle(config: IEditorConfig): void {
|
|
@@ -239,7 +240,7 @@ export class EditBox extends Group implements IEditBox {
|
|
|
239
240
|
|
|
240
241
|
protected onDragStart(e: DragEvent): void {
|
|
241
242
|
this.dragging = true
|
|
242
|
-
const point = this.dragPoint = e.current as IEditPoint
|
|
243
|
+
const point = this.dragPoint = e.current as IEditPoint, { pointType } = point
|
|
243
244
|
const { editor, dragStartData } = this, { element } = editor
|
|
244
245
|
if (point.name === 'rect') {
|
|
245
246
|
this.moving = true
|
|
@@ -250,42 +251,48 @@ export class EditBox extends Group implements IEditBox {
|
|
|
250
251
|
dragStartData.point = { x: element.x, y: element.y } // 用于移动
|
|
251
252
|
dragStartData.bounds = { ...element.getLayoutBounds('box', 'local') } // 用于resize
|
|
252
253
|
dragStartData.rotation = element.rotation // 用于旋转
|
|
254
|
+
if (pointType && pointType.includes('resize')) ResizeEvent.resizingKeys = editor.leafList.keys // 记录正在resize中的元素列表
|
|
253
255
|
}
|
|
254
256
|
|
|
255
257
|
protected onDragEnd(e: DragEvent): void {
|
|
256
258
|
this.dragging = false
|
|
257
259
|
this.dragPoint = null
|
|
258
260
|
this.moving = false
|
|
259
|
-
|
|
261
|
+
const { name, pointType } = e.current as IEditPoint
|
|
262
|
+
if (name === 'rect') this.editor.opacity = 1 // move
|
|
263
|
+
if (pointType && pointType.includes('resize')) ResizeEvent.resizingKeys = null
|
|
260
264
|
}
|
|
261
265
|
|
|
262
266
|
protected onDrag(e: DragEvent): void {
|
|
263
267
|
const { editor } = this
|
|
264
268
|
const { pointType } = this.enterPoint = e.current as IEditPoint
|
|
265
|
-
if (pointType.includes('rotate') || e.metaKey || e.ctrlKey || !editor.mergeConfig.resizeable)
|
|
266
|
-
|
|
269
|
+
if (pointType.includes('rotate') || e.metaKey || e.ctrlKey || !editor.mergeConfig.resizeable) {
|
|
270
|
+
editor.onRotate(e)
|
|
271
|
+
if (pointType === 'resize-rotate') editor.onScale(e)
|
|
272
|
+
} else if (pointType === 'resize') editor.onScale(e)
|
|
267
273
|
if (pointType === 'skew') editor.onSkew(e)
|
|
268
274
|
updateCursor(editor, e)
|
|
269
275
|
}
|
|
270
276
|
|
|
271
277
|
public onArrow(e: IKeyEvent): void {
|
|
272
|
-
|
|
273
|
-
|
|
278
|
+
const { editor } = this
|
|
279
|
+
if (editor.editing && editor.mergeConfig.keyEvent) {
|
|
280
|
+
let x = 0, y = 0
|
|
274
281
|
const distance = e.shiftKey ? 10 : 1
|
|
275
282
|
switch (e.code) {
|
|
276
283
|
case 'ArrowDown':
|
|
277
|
-
|
|
284
|
+
y = distance
|
|
278
285
|
break
|
|
279
286
|
case 'ArrowUp':
|
|
280
|
-
|
|
287
|
+
y = -distance
|
|
281
288
|
break
|
|
282
289
|
case 'ArrowLeft':
|
|
283
|
-
|
|
290
|
+
x = -distance
|
|
284
291
|
break
|
|
285
292
|
case 'ArrowRight':
|
|
286
|
-
|
|
293
|
+
x = distance
|
|
287
294
|
}
|
|
288
|
-
|
|
295
|
+
if (x || y) editor.move(x, y)
|
|
289
296
|
}
|
|
290
297
|
}
|
|
291
298
|
|
package/src/display/EditMask.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { ILeaferCanvas, IRenderOptions } from '@leafer-ui/interface'
|
|
1
|
+
import { IBox, ILeaferCanvas, IRenderOptions } from '@leafer-ui/interface'
|
|
2
2
|
import { UI } from '@leafer-ui/draw'
|
|
3
3
|
|
|
4
4
|
import { IEditor } from '@leafer-in/interface'
|
|
5
5
|
|
|
6
|
+
const bigBounds = { x: 0, y: 0, width: 100000, height: 100000 }
|
|
6
7
|
|
|
7
8
|
export class EditMask extends UI {
|
|
8
9
|
|
|
@@ -12,20 +13,28 @@ export class EditMask extends UI {
|
|
|
12
13
|
super()
|
|
13
14
|
this.editor = editor
|
|
14
15
|
this.hittable = false
|
|
16
|
+
this.visible = 0
|
|
15
17
|
}
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
override __updateWorldBounds(): void {
|
|
20
|
+
Object.assign(this.__local, bigBounds) // 强制修改渲染包围盒
|
|
21
|
+
Object.assign(this.__world, bigBounds)
|
|
22
|
+
}
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
const { rect } = editor.editBox
|
|
23
|
-
const { width, height } = rect.__
|
|
24
|
+
public __draw(canvas: ILeaferCanvas, options: IRenderOptions): void {
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
const { editor } = this, { mask } = editor.mergedConfig
|
|
27
|
+
if (mask && editor.editing) {
|
|
26
28
|
canvas.fillWorld(canvas.bounds, mask === true ? 'rgba(0,0,0,0.8)' : mask)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
if (options.bounds && !options.bounds.hit(editor.editBox.rect.__world, options.matrix)) return
|
|
30
|
+
|
|
31
|
+
canvas.saveBlendMode('destination-out')
|
|
32
|
+
editor.list.forEach(item => {
|
|
33
|
+
item.__renderShape(canvas, options)
|
|
34
|
+
const { __box, parent } = item
|
|
35
|
+
if ((item = __box) || ((item = parent) && (parent as IBox).textBox)) item.__renderShape(canvas, options) // 文本框
|
|
36
|
+
})
|
|
37
|
+
canvas.restoreBlendMode()
|
|
29
38
|
}
|
|
30
39
|
}
|
|
31
40
|
|
|
@@ -189,7 +189,7 @@ export class EditSelect extends Group implements IEditSelect {
|
|
|
189
189
|
protected onDragEnd(e: DragEvent): void {
|
|
190
190
|
if (e.multiTouch) return
|
|
191
191
|
|
|
192
|
-
if (this.dragging) this.originList = null, this.selectArea.visible =
|
|
192
|
+
if (this.dragging) this.originList = null, this.selectArea.visible = 0
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
protected onAutoMove(e: MoveEvent): void {
|
|
@@ -11,7 +11,8 @@ export class SelectArea extends Group implements ISelectArea {
|
|
|
11
11
|
|
|
12
12
|
constructor(data?: IGroupInputData) {
|
|
13
13
|
super(data)
|
|
14
|
-
this.visible =
|
|
14
|
+
this.visible = 0
|
|
15
|
+
this.hittable = false
|
|
15
16
|
this.addMany(this.fillArea, this.strokeArea)
|
|
16
17
|
}
|
|
17
18
|
|
package/src/display/Stroker.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IUI, ILeaferCanvas, IRenderOptions, IRectInputData } from '@leafer-ui/interface'
|
|
1
|
+
import { IUI, ILeaferCanvas, IRenderOptions, IRectInputData, IMatrixWithOptionHalfData } from '@leafer-ui/interface'
|
|
2
2
|
import { Paint, UI, MatrixHelper, getBoundsData, getMatrixData, BoundsHelper, LeafBoundsHelper } from '@leafer-ui/draw'
|
|
3
3
|
|
|
4
4
|
import { IStroker } from '@leafer-in/interface'
|
|
@@ -10,7 +10,7 @@ const { abs } = Math
|
|
|
10
10
|
const { copy, scale } = MatrixHelper
|
|
11
11
|
const { setListWithFn } = BoundsHelper
|
|
12
12
|
const { worldBounds } = LeafBoundsHelper
|
|
13
|
-
const matrix = getMatrixData()
|
|
13
|
+
const matrix = getMatrixData() as IMatrixWithOptionHalfData
|
|
14
14
|
const bounds = getBoundsData()
|
|
15
15
|
|
|
16
16
|
export class Stroker extends UI implements IStroker {
|
|
@@ -22,6 +22,7 @@ export class Stroker extends UI implements IStroker {
|
|
|
22
22
|
|
|
23
23
|
constructor() {
|
|
24
24
|
super()
|
|
25
|
+
this.visible = 0
|
|
25
26
|
this.hittable = false
|
|
26
27
|
this.strokeAlign = 'center'
|
|
27
28
|
}
|
|
@@ -37,9 +38,8 @@ export class Stroker extends UI implements IStroker {
|
|
|
37
38
|
if (list.length) {
|
|
38
39
|
setListWithFn(bounds, list, worldBounds)
|
|
39
40
|
this.set(bounds)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
41
|
+
this.visible = true
|
|
42
|
+
} else this.visible = 0
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
public __draw(canvas: ILeaferCanvas, options: IRenderOptions): void {
|
|
@@ -58,11 +58,12 @@ export class Stroker extends UI implements IStroker {
|
|
|
58
58
|
|
|
59
59
|
const aScaleX = abs(worldTransform.scaleX), aScaleY = abs(worldTransform.scaleY)
|
|
60
60
|
|
|
61
|
+
copy(matrix, worldTransform)
|
|
62
|
+
matrix.half = strokeWidth % 2
|
|
63
|
+
|
|
61
64
|
if (aScaleX !== aScaleY) { // need no scale stroke, use rect path
|
|
62
65
|
|
|
63
|
-
copy(matrix, worldTransform)
|
|
64
66
|
scale(matrix, 1 / aScaleX, 1 / aScaleY)
|
|
65
|
-
|
|
66
67
|
canvas.setWorld(matrix, options.matrix)
|
|
67
68
|
canvas.beginPath()
|
|
68
69
|
data.strokeWidth = strokeWidth
|
|
@@ -72,7 +73,7 @@ export class Stroker extends UI implements IStroker {
|
|
|
72
73
|
|
|
73
74
|
} else {
|
|
74
75
|
|
|
75
|
-
canvas.setWorld(
|
|
76
|
+
canvas.setWorld(matrix, options.matrix)
|
|
76
77
|
canvas.beginPath()
|
|
77
78
|
|
|
78
79
|
if (leaf.__.__useArrow) leaf.__drawPath(canvas)
|
|
@@ -99,10 +99,10 @@ export const EditDataHelper = {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
const useScaleX = scaleX !== 1, useScaleY = scaleY !== 1
|
|
102
103
|
|
|
103
|
-
scaleX /= changedScaleX
|
|
104
|
-
scaleY /= changedScaleY
|
|
105
|
-
|
|
104
|
+
if (useScaleX) scaleX /= changedScaleX
|
|
105
|
+
if (useScaleY) scaleY /= changedScaleY
|
|
106
106
|
|
|
107
107
|
if (!flipable) {
|
|
108
108
|
const { worldTransform } = element
|
|
@@ -121,24 +121,27 @@ export const EditDataHelper = {
|
|
|
121
121
|
|
|
122
122
|
if (!BoundsHelper.includes(allowBounds, localBounds)) {
|
|
123
123
|
const realBounds = localBounds.getIntersect(allowBounds)
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
const fitScaleX = realBounds.width / localBounds.width, fitScaleY = realBounds.height / localBounds.height
|
|
125
|
+
if (useScaleX) scaleX *= fitScaleX
|
|
126
|
+
if (useScaleY) scaleY *= fitScaleY // 后续需优化带旋转的场景
|
|
126
127
|
}
|
|
127
128
|
}
|
|
128
129
|
|
|
129
|
-
if (widthRange) {
|
|
130
|
+
if (useScaleX && widthRange) {
|
|
130
131
|
const nowWidth = boxBounds.width * element.scaleX
|
|
131
132
|
scaleX = within(nowWidth * scaleX, widthRange) / nowWidth
|
|
132
133
|
}
|
|
133
134
|
|
|
134
|
-
if (heightRange) {
|
|
135
|
+
if (useScaleY && heightRange) {
|
|
135
136
|
const nowHeight = boxBounds.height * element.scaleY
|
|
136
137
|
scaleY = within(nowHeight * scaleY, heightRange) / nowHeight
|
|
137
138
|
}
|
|
138
139
|
|
|
139
140
|
// 防止小于1px
|
|
140
|
-
if (Math.abs(scaleX * worldBoxBounds.width) < 1) scaleX = (scaleX < 0 ? -1 : 1) / worldBoxBounds.width
|
|
141
|
-
if (Math.abs(scaleY * worldBoxBounds.height) < 1) scaleY = (scaleY < 0 ? -1 : 1) / worldBoxBounds.height
|
|
141
|
+
if (useScaleX && Math.abs(scaleX * worldBoxBounds.width) < 1) scaleX = (scaleX < 0 ? -1 : 1) / worldBoxBounds.width
|
|
142
|
+
if (useScaleY && Math.abs(scaleY * worldBoxBounds.height) < 1) scaleY = (scaleY < 0 ? -1 : 1) / worldBoxBounds.height
|
|
143
|
+
|
|
144
|
+
if (lockRatio && scaleX !== scaleY) scaleY = scaleX = Math.min(scaleX, scaleY)
|
|
142
145
|
|
|
143
146
|
return { origin, scaleX, scaleY, direction, lockRatio, around }
|
|
144
147
|
},
|
package/src/tool/EditTool.ts
CHANGED
|
@@ -21,9 +21,7 @@ export class EditTool extends InnerEditor implements IEditTool {
|
|
|
21
21
|
const { moveX, moveY, editor } = e
|
|
22
22
|
const { app, list } = editor
|
|
23
23
|
app.lockLayout()
|
|
24
|
-
list.forEach(target => {
|
|
25
|
-
target.moveWorld(moveX, moveY)
|
|
26
|
-
})
|
|
24
|
+
list.forEach(target => { target.moveWorld(moveX, moveY) })
|
|
27
25
|
app.unlockLayout()
|
|
28
26
|
}
|
|
29
27
|
|
|
@@ -33,11 +31,8 @@ export class EditTool extends InnerEditor implements IEditTool {
|
|
|
33
31
|
app.lockLayout()
|
|
34
32
|
list.forEach(target => {
|
|
35
33
|
const resize = editor.getEditSize(target) !== 'scale'
|
|
36
|
-
if (transform)
|
|
37
|
-
|
|
38
|
-
} else {
|
|
39
|
-
target.scaleOfWorld(worldOrigin, scaleX, scaleY, resize)
|
|
40
|
-
}
|
|
34
|
+
if (transform) target.transformWorld(transform, resize)
|
|
35
|
+
else target.scaleOfWorld(worldOrigin, scaleX, scaleY, resize)
|
|
41
36
|
})
|
|
42
37
|
app.unlockLayout()
|
|
43
38
|
}
|
|
@@ -48,11 +43,8 @@ export class EditTool extends InnerEditor implements IEditTool {
|
|
|
48
43
|
app.lockLayout()
|
|
49
44
|
list.forEach(target => {
|
|
50
45
|
const resize = editor.getEditSize(target) !== 'scale'
|
|
51
|
-
if (transform)
|
|
52
|
-
|
|
53
|
-
} else {
|
|
54
|
-
target.rotateOfWorld(worldOrigin, rotation)
|
|
55
|
-
}
|
|
46
|
+
if (transform) target.transformWorld(transform, resize)
|
|
47
|
+
else target.rotateOfWorld(worldOrigin, rotation)
|
|
56
48
|
})
|
|
57
49
|
app.unlockLayout()
|
|
58
50
|
}
|
|
@@ -63,11 +55,8 @@ export class EditTool extends InnerEditor implements IEditTool {
|
|
|
63
55
|
app.lockLayout()
|
|
64
56
|
list.forEach(target => {
|
|
65
57
|
const resize = editor.getEditSize(target) !== 'scale'
|
|
66
|
-
if (transform)
|
|
67
|
-
|
|
68
|
-
} else {
|
|
69
|
-
target.skewOfWorld(worldOrigin, skewX, skewY, resize)
|
|
70
|
-
}
|
|
58
|
+
if (transform) target.transformWorld(transform, resize)
|
|
59
|
+
else target.skewOfWorld(worldOrigin, skewX, skewY, resize)
|
|
71
60
|
})
|
|
72
61
|
app.unlockLayout()
|
|
73
62
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { IBounds, ILeafList, IUI, IFunction, IEventListenerId, ILeaf, IPointerEvent, ILeaferCanvas, IRenderOptions, IGroup, IObject, IGroupInputData, IEditSize, IPointData, IAlign, IAxis, IMatrix, IBox, IEditorDragStartData, IBoundsData, IEditorConfig as IEditorConfig$1, IBoxInputData, IKeyEvent, IRect, IRectInputData, IMatrixData, IDragEvent, IAround, ILayoutBoundsData } from '@leafer-ui/interface';
|
|
1
|
+
import { IBounds, ILeafList, IUI, IFunction, IEventListenerId, ILeaf, IPointerEvent, ILeaferCanvas, IRenderOptions, IGroup, IObject, IGroupInputData, IEditSize, IPointData, IAlign, IAxis, IMatrix, IApp, IBox, IEditorDragStartData, IBoundsData, IEditorConfig as IEditorConfig$1, IBoxInputData, IKeyEvent, IRect, IRectInputData, IMatrixData, IDragEvent, IAround, ILayoutBoundsData } from '@leafer-ui/interface';
|
|
2
2
|
import { Group, UI, Direction9, Event, Box } from '@leafer-ui/draw';
|
|
3
|
-
import { PointerEvent, DragEvent, MoveEvent, ZoomEvent, RotateEvent } from '@leafer-ui/core';
|
|
3
|
+
import { PointerEvent, DragEvent, MoveEvent, ZoomEvent, RotateEvent, KeyEvent } from '@leafer-ui/core';
|
|
4
4
|
import { IEditSelect, IEditor, IStroker, ISelectArea, IEditorConfig, IEditPoint, ISimulateElement, IEditBox, IEditTool, IInnerEditor, IEditorScaleEvent, IEditorEvent, IEditPointType, IEditorMoveEvent, IEditorRotateEvent, IEditorSkewEvent, IEditorGroupEvent, IInnerEditorEvent, 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 {
|
|
@@ -42,13 +42,15 @@ declare class EditSelect extends Group implements IEditSelect {
|
|
|
42
42
|
declare class EditMask extends UI {
|
|
43
43
|
editor: IEditor;
|
|
44
44
|
constructor(editor: IEditor);
|
|
45
|
+
__updateWorldBounds(): void;
|
|
45
46
|
__draw(canvas: ILeaferCanvas, options: IRenderOptions): void;
|
|
46
47
|
destroy(): void;
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
declare class Editor extends Group implements IEditor {
|
|
50
51
|
config: IEditorConfig;
|
|
51
|
-
|
|
52
|
+
readonly mergeConfig: IEditorConfig;
|
|
53
|
+
readonly mergedConfig: IEditorConfig;
|
|
52
54
|
hoverTarget?: IUI;
|
|
53
55
|
target?: IUI | IUI[];
|
|
54
56
|
leafList: ILeafList;
|
|
@@ -73,6 +75,7 @@ declare class Editor extends Group implements IEditor {
|
|
|
73
75
|
editToolList: IObject;
|
|
74
76
|
selector: EditSelect;
|
|
75
77
|
editMask: EditMask;
|
|
78
|
+
targetChanged: boolean;
|
|
76
79
|
targetEventIds: IEventListenerId[];
|
|
77
80
|
constructor(userConfig?: IEditorConfig, data?: IGroupInputData);
|
|
78
81
|
select(target: IUI | IUI[]): void;
|
|
@@ -112,6 +115,9 @@ declare class Editor extends Group implements IEditor {
|
|
|
112
115
|
unlock(): void;
|
|
113
116
|
toTop(): void;
|
|
114
117
|
toBottom(): void;
|
|
118
|
+
protected onAppRenderStart(app: IApp): void;
|
|
119
|
+
protected onRenderStart(): void;
|
|
120
|
+
protected onKey(e: KeyEvent): void;
|
|
115
121
|
listenTargetEvents(): void;
|
|
116
122
|
removeTargetEvents(): void;
|
|
117
123
|
destroy(): void;
|