@leafer-in/editor 1.0.0-rc.6 → 1.0.0-rc.7

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.
@@ -0,0 +1,14 @@
1
+ import { IGroup, ILeaf } from '@leafer-ui/interface'
2
+ import { Bounds } from '@leafer-ui/core'
3
+
4
+ import { IEditor } from '@leafer-in/interface'
5
+
6
+
7
+ export function simulate(editor: IEditor) {
8
+ const { simulateTarget, leafList: targetList } = editor
9
+ const { x, y, width, height } = new Bounds().setListWithFn(targetList.list, (leaf: ILeaf) => leaf.worldBoxBounds)
10
+
11
+ const parent = simulateTarget.parent = targetList.list[0].leafer.zoomLayer as IGroup
12
+ const { scaleX, scaleY, e: worldX, f: worldY } = parent.__world
13
+ simulateTarget.reset({ x: (x - worldX) / scaleX, y: (y - worldY) / scaleY, width: width / scaleX, height: height / scaleY })
14
+ }
@@ -0,0 +1,38 @@
1
+ import { LeafList } from '@leafer-ui/core'
2
+
3
+ import { IEditor, IUI } from '@leafer-in/interface'
4
+
5
+ import { simulate } from './simulate'
6
+ import { updateMoveCursor } from './cursor'
7
+ import { EditorEvent } from '../event/EditorEvent'
8
+
9
+
10
+ export function onTarget(editor: IEditor): void {
11
+ const { target } = editor
12
+ if (target) {
13
+ editor.leafList = target instanceof LeafList ? target : new LeafList(target instanceof Array ? target : target as IUI)
14
+ } else {
15
+ editor.leafList.reset()
16
+ }
17
+
18
+ editor.emitEvent(new EditorEvent(EditorEvent.SELECT, { editor }))
19
+
20
+ if (editor.hasTarget) {
21
+ editor.waitLeafer(() => {
22
+ if (editor.multiple) simulate(editor)
23
+ updateMoveCursor(editor)
24
+ editor.updateEditTool()
25
+ editor.update()
26
+ editor.listenTargetEvents()
27
+ })
28
+ } else {
29
+ editor.removeTargetEvents()
30
+ }
31
+ }
32
+
33
+
34
+
35
+ export function onHover(editor: IEditor): void {
36
+ editor.emitEvent(new EditorEvent(EditorEvent.HOVER, { editor }))
37
+
38
+ }
@@ -0,0 +1,23 @@
1
+ import { IUI, IPointData } from '@leafer-ui/interface'
2
+ import { Event } from '@leafer-ui/core'
3
+
4
+ import { IEditor, IEditorEvent } from '@leafer-in/interface'
5
+
6
+
7
+ export class EditorEvent extends Event implements IEditorEvent {
8
+
9
+ static SELECT = 'editor.select'
10
+ static HOVER = 'editor.hover'
11
+
12
+ declare readonly target: IUI
13
+ readonly editor: IEditor
14
+
15
+ readonly worldOrigin: IPointData
16
+ declare readonly origin: IPointData
17
+
18
+ constructor(type: string, data?: IEditorEvent) {
19
+ super(type)
20
+ if (data) Object.assign(this, data)
21
+ }
22
+
23
+ }
@@ -0,0 +1,17 @@
1
+ import { IEditorMoveEvent } from '@leafer-in/interface'
2
+
3
+ import { EditorEvent } from './EditorEvent'
4
+
5
+
6
+ export class EditorMoveEvent extends EditorEvent implements IEditorMoveEvent {
7
+
8
+ static MOVE = 'editor.move'
9
+
10
+ readonly moveX: number
11
+ readonly moveY: number
12
+
13
+ constructor(type: string, data?: IEditorMoveEvent) {
14
+ super(type, data)
15
+ }
16
+
17
+ }
@@ -1,23 +1,17 @@
1
- import { IUI, IPointData } from '@leafer-ui/interface'
2
- import { IEditor, IEditorRotateEvent } from '@leafer-in/interface'
1
+ import { IEditorRotateEvent } from '@leafer-in/interface'
3
2
 
4
- import { Event } from '@leafer-ui/core'
3
+ import { EditorEvent } from './EditorEvent'
5
4
 
6
5
 
7
- export class EditorRotateEvent extends Event implements IEditorRotateEvent {
6
+ export class EditorRotateEvent extends EditorEvent implements IEditorRotateEvent {
8
7
 
9
8
  static ROTATE = 'editor.rotate'
10
9
 
11
- declare readonly target: IUI
12
- readonly editor: IEditor
13
-
14
10
  // rotateOf(origin, rotation)
15
- declare readonly origin: IPointData
16
11
  readonly rotation: number
17
12
 
18
13
  constructor(type: string, data?: IEditorRotateEvent) {
19
- super(type)
20
- if (data) Object.assign(this, data)
14
+ super(type, data)
21
15
  }
22
16
 
23
17
  }
@@ -0,0 +1,27 @@
1
+ import { IAround, IDragEvent, IMatrixData } from '@leafer-ui/interface'
2
+
3
+ import { IDirection8, IEditorScaleEvent } from '@leafer-in/interface'
4
+
5
+ import { EditorEvent } from './EditorEvent'
6
+
7
+
8
+ export class EditorScaleEvent extends EditorEvent implements IEditorScaleEvent {
9
+
10
+ static SCALE = 'editor.scale'
11
+
12
+ // scaleOf(origin, scaleX, scaleY, resize)
13
+ readonly scaleX: number
14
+ readonly scaleY: number
15
+ readonly transform?: IMatrixData
16
+
17
+ readonly drag: IDragEvent
18
+
19
+ readonly direction: IDirection8
20
+ readonly lockRatio: boolean
21
+ readonly around: IAround
22
+
23
+ constructor(type: string, data?: IEditorScaleEvent) {
24
+ super(type, data)
25
+ }
26
+
27
+ }
@@ -0,0 +1,18 @@
1
+ import { IEditorSkewEvent } from '@leafer-in/interface'
2
+
3
+ import { EditorEvent } from './EditorEvent'
4
+
5
+
6
+ export class EditorSkewEvent extends EditorEvent implements IEditorSkewEvent {
7
+
8
+ static SKEW = 'editor.skew'
9
+
10
+ // skewOf(origin, skewX, skewY)
11
+ readonly skewX: number
12
+ readonly skewY: number
13
+
14
+ constructor(type: string, data?: IEditorSkewEvent) {
15
+ super(type, data)
16
+ }
17
+
18
+ }
@@ -0,0 +1,149 @@
1
+ import { IBoundsData, IPointData, IAround } from '@leafer-ui/interface'
2
+ import { AroundHelper, PointHelper } from '@leafer-ui/core'
3
+
4
+ import { IEditorScaleEvent, IDirection8, IEditorSkewEvent, IEditorRotateEvent } from '@leafer-in/interface'
5
+
6
+
7
+ const { topLeft, top, topRight, right, bottomRight, bottom, bottomLeft, left } = IDirection8
8
+ const { toPoint } = AroundHelper
9
+
10
+ export const EditDataHelper = {
11
+
12
+ getScaleData(bounds: IBoundsData, direction: IDirection8, pointMove: IPointData, lockRatio: boolean, around: IAround): IEditorScaleEvent {
13
+ let origin: IPointData, scaleX: number = 1, scaleY: number = 1
14
+ const { width, height } = bounds
15
+
16
+ if (around) {
17
+ pointMove.x *= 2
18
+ pointMove.y *= 2
19
+ }
20
+
21
+ const topScale = (-pointMove.y + height) / height
22
+ const rightScale = (pointMove.x + width) / width
23
+ const bottomScale = (pointMove.y + height) / height
24
+ const leftScale = (-pointMove.x + width) / width
25
+
26
+ switch (direction) {
27
+ case top:
28
+ scaleY = topScale
29
+ origin = { x: 0.5, y: 1 }
30
+ break
31
+ case right:
32
+ scaleX = rightScale
33
+ origin = { x: 0, y: 0.5 }
34
+ break
35
+ case bottom:
36
+ scaleY = bottomScale
37
+ origin = { x: 0.5, y: 0 }
38
+ break
39
+ case left:
40
+ scaleX = leftScale
41
+ origin = { x: 1, y: 0.5 }
42
+ break
43
+ case topLeft:
44
+ scaleY = topScale
45
+ scaleX = leftScale
46
+ origin = { x: 1, y: 1 }
47
+ break
48
+ case topRight:
49
+ scaleY = topScale
50
+ scaleX = rightScale
51
+ origin = { x: 0, y: 1 }
52
+ break
53
+ case bottomRight:
54
+ scaleY = bottomScale
55
+ scaleX = rightScale
56
+ origin = { x: 0, y: 0 }
57
+ break
58
+ case bottomLeft:
59
+ scaleY = bottomScale
60
+ scaleX = leftScale
61
+ origin = { x: 1, y: 0 }
62
+ }
63
+
64
+ if (lockRatio) {
65
+ if (scaleX !== 1) scaleY = scaleX
66
+ else scaleX = scaleY
67
+ }
68
+
69
+ toPoint(around || origin, bounds, origin)
70
+
71
+ return { origin, scaleX, scaleY, direction, lockRatio, around }
72
+ },
73
+
74
+ getRotateData(bounds: IBoundsData, direction: IDirection8, current: IPointData, last: IPointData, around: IAround): IEditorRotateEvent {
75
+ let origin: IPointData
76
+
77
+ switch (direction) {
78
+ case topLeft:
79
+ origin = { x: 1, y: 1 }
80
+ break
81
+ case topRight:
82
+ origin = { x: 0, y: 1 }
83
+ break
84
+ case bottomRight:
85
+ origin = { x: 0, y: 0 }
86
+ break
87
+ case bottomLeft:
88
+ origin = { x: 1, y: 0 }
89
+ break
90
+ default:
91
+ origin = { x: 0.5, y: 0.5 }
92
+ }
93
+
94
+ toPoint(around || origin, bounds, origin)
95
+
96
+ return { origin, rotation: PointHelper.getRotation(last, origin, current) }
97
+ },
98
+
99
+ getSkewData(bounds: IBoundsData, direction: IDirection8, move: IPointData, around: IAround): IEditorSkewEvent {
100
+ let origin: IPointData, skewX = 0, skewY = 0
101
+ let last: IPointData
102
+
103
+ switch (direction) {
104
+ case top:
105
+ last = { x: 0.5, y: 0 }
106
+ origin = { x: 0.5, y: 1 }
107
+ skewX = 1
108
+ break
109
+ case bottom:
110
+ last = { x: 0.5, y: 1 }
111
+ origin = { x: 0.5, y: 0 }
112
+ skewX = 1
113
+ break
114
+ case left:
115
+ last = { x: 0, y: 0.5 }
116
+ origin = { x: 1, y: 0.5 }
117
+ skewY = 1
118
+ break
119
+ case right:
120
+ last = { x: 1, y: 0.5 }
121
+ origin = { x: 0, y: 0.5 }
122
+ skewY = 1
123
+ }
124
+
125
+ const { x, y, width, height } = bounds
126
+
127
+ last.x = x + last.x * width
128
+ last.y = y + last.y * height
129
+
130
+ toPoint(around || origin, bounds, origin)
131
+
132
+ const rotation = PointHelper.getRotation(last, origin, { x: last.x + (skewX ? move.x : 0), y: last.y + (skewY ? move.y : 0) })
133
+ skewX ? skewX = -rotation : skewY = rotation
134
+
135
+ return { origin, skewX, skewY }
136
+ },
137
+
138
+
139
+ getAround(around: IAround, altKey: boolean): IAround {
140
+ return (altKey && !around) ? AroundHelper.center : around
141
+ },
142
+
143
+ getRotateDirection(direction: number, rotation: number, totalDirection = 8): number {
144
+ direction = (direction + Math.round(rotation / (360 / totalDirection))) % totalDirection
145
+ if (direction < 0) direction += totalDirection
146
+ return direction
147
+ }
148
+
149
+ }
@@ -0,0 +1,33 @@
1
+ import { AnswerType, IBounds, ILeafList, IUI } from '@leafer-ui/interface'
2
+
3
+ const { No, Yes, NoAndSkip, YesAndSkip } = AnswerType
4
+
5
+ export const EditSelectHelper = {
6
+
7
+ findOne(path: ILeafList): IUI {
8
+ return path.list.find((leaf) => leaf.editable) as IUI
9
+ },
10
+
11
+ findBounds(leaf: IUI, bounds: IBounds): AnswerType {
12
+ if (leaf.__.hittable && !leaf.__.locked && bounds.hit(leaf.__world)) {
13
+
14
+ if (leaf.__.editable) {
15
+ if (leaf.isBranch && !leaf.__.hitChildren) {
16
+ return leaf.__.hitSelf ? YesAndSkip : NoAndSkip
17
+ } else if (leaf.isFrame) {
18
+ return bounds.includes(leaf.__layout.boxBounds, leaf.__world) ? YesAndSkip : No
19
+ } else {
20
+ if (bounds.hit(leaf.__layout.boxBounds, leaf.__world) && leaf.__.hitSelf) return Yes
21
+ }
22
+ }
23
+
24
+ return No
25
+
26
+ } else {
27
+
28
+ return leaf.isBranch ? NoAndSkip : No
29
+
30
+ }
31
+ }
32
+
33
+ }
@@ -0,0 +1,95 @@
1
+ import { IGroup, ILeaf, IUI } from '@leafer-ui/interface'
2
+ import { Group, Matrix } from '@leafer-ui/core'
3
+
4
+
5
+ const order = (a: ILeaf, b: ILeaf) => a.parent.children.indexOf(a) - b.parent.children.indexOf(b)
6
+ const reverseOrder = (a: ILeaf, b: ILeaf) => b.parent.children.indexOf(b) - a.parent.children.indexOf(a)
7
+
8
+ export const EditorHelper = {
9
+
10
+ group(list: IUI[], element?: IUI, group?: IGroup): IGroup {
11
+ list.sort(reverseOrder)
12
+ const { app, parent } = list[0]
13
+ if (!group) group = new Group()
14
+ parent.addAt(group, parent.children.indexOf(list[0]))
15
+ list.sort(order)
16
+
17
+ const matrx = new Matrix(element.worldTransform)
18
+ matrx.divideParent(parent.worldTransform)
19
+ group.setTransform(matrx)
20
+ group.editable = true
21
+ group.hitChildren = false
22
+
23
+ app.lockLayout()
24
+ list.forEach(child => child.dropTo(group))
25
+ app.unlockLayout()
26
+
27
+ return group
28
+ },
29
+
30
+ ungroup(list: IUI[]): IUI[] {
31
+ const { app } = list[0]
32
+ const ungroupList: IUI[] = []
33
+
34
+ app.lockLayout()
35
+ list.forEach(leaf => {
36
+ if (leaf.isBranch) {
37
+ const { parent, children } = leaf
38
+ while (children.length) {
39
+ ungroupList.push(children[0])
40
+ children[0].dropTo(parent, parent.children.indexOf(leaf))
41
+ }
42
+ leaf.remove()
43
+ } else {
44
+ ungroupList.push(leaf)
45
+ }
46
+ })
47
+ app.unlockLayout()
48
+
49
+ return ungroupList
50
+ },
51
+
52
+ toTop(list: IUI[]): void {
53
+ list.sort(order)
54
+ list.forEach(leaf => {
55
+ let zIndex
56
+ const { parent } = leaf
57
+ if (parent) {
58
+ const { children } = parent
59
+ const top = children.length - 1
60
+ const zIndexOfTop = children[top].__.zIndex
61
+ const current = children.indexOf(leaf)
62
+ if (current !== top) {
63
+ children.splice(current, 1)
64
+ children.push(leaf)
65
+ zIndex = zIndexOfTop + 1
66
+ } else {
67
+ zIndex = zIndexOfTop
68
+ }
69
+ leaf.zIndex = zIndex
70
+ }
71
+ })
72
+ },
73
+
74
+ toBottom(list: IUI[]): void {
75
+ list.sort(reverseOrder)
76
+ list.forEach(leaf => {
77
+ let zIndex
78
+ const { parent } = leaf
79
+ if (parent) {
80
+ const { children } = parent
81
+ const zIndexOfBottom = children[0].__.zIndex
82
+ const current = children.indexOf(leaf)
83
+ if (current !== 0) {
84
+ children.splice(current, 1)
85
+ children.unshift(leaf)
86
+ zIndex = zIndexOfBottom - 1
87
+ } else {
88
+ zIndex = zIndexOfBottom
89
+ }
90
+ leaf.zIndex = zIndex
91
+ }
92
+ })
93
+ }
94
+
95
+ }
package/src/index.ts CHANGED
@@ -1,5 +1,28 @@
1
1
  export { Editor } from './Editor'
2
- export { EditorResizeEvent } from './event/EditorResizeEvent'
2
+
3
+ export { EditBox } from './display/EditBox'
4
+ export { EditPoint } from './display/EditPoint'
5
+ export { EditSelect } from './display/EditSelect'
6
+ export { SelectArea } from './display/SelectArea'
7
+ export { Stroker } from './display/Stroker'
8
+
9
+ export { EditorEvent } from './event/EditorEvent'
10
+ export { EditorMoveEvent } from './event/EditorMoveEvent'
11
+ export { EditorScaleEvent } from './event/EditorScaleEvent'
3
12
  export { EditorRotateEvent } from './event/EditorRotateEvent'
4
- export { LineTool } from './tool/LineTool'
5
- export { RectTool } from './tool/RectTool'
13
+ export { EditorSkewEvent } from './event/EditorSkewEvent'
14
+
15
+ export { LineEditTool } from './tool/LineEditTool'
16
+ export { EditTool } from './tool/EditTool'
17
+
18
+ export { EditorHelper } from './helper/EditorHelper'
19
+ export { EditDataHelper } from './helper/EditDataHelper'
20
+ export { EditSelectHelper } from './helper/EditSelectHelper'
21
+
22
+ import { IEditor, IEditorConfig } from '@leafer-in/interface'
23
+ import { Creator } from '@leafer-ui/core'
24
+ import { Editor } from './Editor'
25
+
26
+ Creator.editor = function (options?: IEditorConfig): IEditor {
27
+ return new Editor(options)
28
+ }
@@ -0,0 +1,70 @@
1
+ import { IEditor, IEditorScaleEvent, IEditorRotateEvent, IEditTool, IEditorSkewEvent, IEditorMoveEvent } from '@leafer-in/interface'
2
+
3
+ export class EditTool implements IEditTool {
4
+
5
+ static list: IEditTool[] = []
6
+
7
+ public tag = 'EditTool'
8
+
9
+ onMove(e: IEditorMoveEvent): void {
10
+ const { moveX, moveY, editor } = e
11
+ const { app, list } = editor
12
+ app.lockLayout()
13
+ list.forEach(target => {
14
+ const move = target.getLocalPoint({ x: moveX, y: moveY }, null, true)
15
+ target.move(move.x, move.y)
16
+ })
17
+ app.unlockLayout()
18
+ }
19
+
20
+ onScale(e: IEditorScaleEvent): void {
21
+ const { scaleX, scaleY, transform, worldOrigin, editor } = e
22
+ const { app, list } = editor
23
+ app.lockLayout()
24
+ list.forEach(target => {
25
+ const resize = editor.getEditSize(target) === 'size'
26
+ if (transform) {
27
+ target.transform(transform, resize)
28
+ } else {
29
+ target.scaleOf(target.getInnerPoint(worldOrigin), scaleX, scaleY, resize)
30
+ }
31
+ })
32
+ app.unlockLayout()
33
+ }
34
+
35
+ onRotate(e: IEditorRotateEvent): void {
36
+ const { rotation, worldOrigin, editor } = e
37
+ const { app, list } = editor
38
+ app.lockLayout()
39
+ list.forEach(target => {
40
+ target.rotateOf(target.getInnerPoint(worldOrigin), rotation)
41
+ })
42
+ app.unlockLayout()
43
+ }
44
+
45
+ onSkew(e: IEditorSkewEvent): void {
46
+ const { skewX, skewY, transform, worldOrigin, editor } = e
47
+ const { app, list } = editor
48
+ app.lockLayout()
49
+ list.forEach(target => {
50
+ const resize = editor.getEditSize(target) === 'size'
51
+ if (transform) {
52
+ target.transform(transform, resize)
53
+ } else {
54
+ target.skewOf(target.getInnerPoint(worldOrigin), skewX, skewY, resize)
55
+ }
56
+ })
57
+ app.unlockLayout()
58
+ }
59
+
60
+ update(editor: IEditor) {
61
+ const { simulateTarget, element } = editor
62
+
63
+ if (editor.multiple) simulateTarget.parent.updateLayout()
64
+
65
+ const { x, y, scaleX, scaleY, rotation, skewX, skewY, width, height } = element.getLayoutBounds('box', editor, true)
66
+ editor.editBox.set({ x, y, scaleX, scaleY, rotation, skewX, skewY })
67
+ editor.editBox.update({ x: 0, y: 0, width, height })
68
+ }
69
+
70
+ }
@@ -1,23 +1,18 @@
1
- import { IDirection8, IEditor, IEditorTool, IEditorResizeEvent, IEditorRotateEvent, ILine, IPointData } from '@leafer-in/interface'
1
+ import { IDirection8, IEditor, IEditorScaleEvent, ILine, IEditorSkewEvent } from '@leafer-in/interface'
2
2
 
3
- import { RectTool } from './RectTool'
3
+ import { EditTool } from './EditTool'
4
4
 
5
5
 
6
6
  const { left, right } = IDirection8
7
7
 
8
- export const LineTool: IEditorTool = {
8
+ export class LineEditTool extends EditTool {
9
9
 
10
- name: 'LineTool',
10
+ public tag = 'LineEditTool'
11
11
 
12
- getMirrorData(_editor: IEditor): IPointData {
13
- return {
14
- x: 0,
15
- y: 0
16
- }
17
- },
12
+ public scaleOfEvent = true
18
13
 
19
- resize(e: IEditorResizeEvent): void {
20
- const { direction, dragEvent, lockRatio, around } = e
14
+ onScaleWithDrag(e: IEditorScaleEvent): void {
15
+ const { drag, direction, lockRatio, around } = e
21
16
  const target = e.target as ILine
22
17
 
23
18
  const fromPoint = { x: 0, y: 0 }
@@ -25,7 +20,7 @@ export const LineTool: IEditorTool = {
25
20
 
26
21
  target.rotation = 0
27
22
 
28
- let { x, y } = dragEvent.getInnerMove(target)
23
+ let { x, y } = drag.getInnerMove(target)
29
24
 
30
25
  if (lockRatio) {
31
26
  if (Math.abs(x) > Math.abs(y)) {
@@ -65,24 +60,20 @@ export const LineTool: IEditorTool = {
65
60
  target.getInnerPointByLocal(toPoint, null, null, true)
66
61
  target.toPoint = toPoint
67
62
 
68
- },
63
+ }
69
64
 
70
- rotate(e: IEditorRotateEvent): void {
71
- RectTool.rotate(e)
72
- },
65
+ onSkew(_e: IEditorSkewEvent): void {
73
66
 
74
- update(editor: IEditor) {
67
+ }
75
68
 
76
- const { rotatePoints, circle, resizeLines, resizePoints } = editor
77
- RectTool.update(editor)
69
+ update(editor: IEditor) {
70
+ const { rotatePoints, resizeLines, resizePoints } = editor.editBox
71
+ super.update(editor)
78
72
 
79
73
  for (let i = 0; i < 8; i++) {
80
74
  if (i < 4) resizeLines[i].visible = false
81
- resizePoints[i].visible = rotatePoints[i].visible = i === left || i === right
75
+ resizePoints[i].visible = rotatePoints[i].visible = (i === left || i === right)
82
76
  }
83
-
84
- circle.visible = false
85
-
86
77
  }
87
78
 
88
79
  }
@@ -0,0 +1,21 @@
1
+ import { IUI } from '@leafer-ui/interface'
2
+ import { Line } from '@leafer-ui/core'
3
+
4
+ import { IEditTool } from '@leafer-in/interface'
5
+
6
+ import { EditTool } from './EditTool'
7
+ import { LineEditTool } from './LineEditTool'
8
+
9
+
10
+ export function getEditTool(list: IUI[]): IEditTool {
11
+ if (list.length === 1) {
12
+ const leaf = list[0]
13
+ if (leaf instanceof Line && !leaf.points) {
14
+ return new LineEditTool()
15
+ } else {
16
+ return new EditTool()
17
+ }
18
+ } else {
19
+ return new EditTool()
20
+ }
21
+ }