@leafer-in/editor 1.0.0-beta.15
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/LICENSE +21 -0
- package/README.md +3 -0
- package/dist/editor.esm.js +510 -0
- package/dist/editor.esm.min.js +1 -0
- package/dist/editor.js +520 -0
- package/dist/editor.min.js +1 -0
- package/package.json +39 -0
- package/src/Editor.ts +232 -0
- package/src/cursor.ts +57 -0
- package/src/event/EditorResizeEvent.ts +34 -0
- package/src/event/EditorRotateEvent.ts +23 -0
- package/src/index.ts +5 -0
- package/src/resize.ts +87 -0
- package/src/tool/LineTool.ts +88 -0
- package/src/tool/RectTool.ts +139 -0
- package/types/index.d.ts +68 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023-present, Chao (Leafer) Wan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
import { MatrixHelper, Bounds, Matrix, Event, Group, Rect, Polygon, DataHelper, RotateEvent, PointHelper, MathHelper, DragEvent, PointerEvent, RenderEvent, KeyEvent } from '@leafer-ui/core';
|
|
2
|
+
|
|
3
|
+
var IDirection8;
|
|
4
|
+
(function (IDirection8) {
|
|
5
|
+
IDirection8[IDirection8["topLeft"] = 0] = "topLeft";
|
|
6
|
+
IDirection8[IDirection8["top"] = 1] = "top";
|
|
7
|
+
IDirection8[IDirection8["topRight"] = 2] = "topRight";
|
|
8
|
+
IDirection8[IDirection8["right"] = 3] = "right";
|
|
9
|
+
IDirection8[IDirection8["bottomRight"] = 4] = "bottomRight";
|
|
10
|
+
IDirection8[IDirection8["bottom"] = 5] = "bottom";
|
|
11
|
+
IDirection8[IDirection8["bottomLeft"] = 6] = "bottomLeft";
|
|
12
|
+
IDirection8[IDirection8["left"] = 7] = "left";
|
|
13
|
+
})(IDirection8 || (IDirection8 = {}));
|
|
14
|
+
|
|
15
|
+
const { scaleOfOuter, reset } = MatrixHelper;
|
|
16
|
+
const { topLeft: topLeft$1, top: top$1, topRight: topRight$1, right: right$2, bottomRight: bottomRight$1, bottom: bottom$1, bottomLeft: bottomLeft$1, left: left$2 } = IDirection8;
|
|
17
|
+
const matrix = {};
|
|
18
|
+
function getResizeData(old, direction, move, lockRatio, around) {
|
|
19
|
+
if (around) {
|
|
20
|
+
move.x *= 2;
|
|
21
|
+
move.y *= 2;
|
|
22
|
+
}
|
|
23
|
+
let origin, scaleX = 1, scaleY = 1;
|
|
24
|
+
const { x, y, width, height } = old;
|
|
25
|
+
const topScale = (-move.y + height) / height;
|
|
26
|
+
const rightScale = (move.x + width) / width;
|
|
27
|
+
const bottomScale = (move.y + height) / height;
|
|
28
|
+
const leftScale = (-move.x + width) / width;
|
|
29
|
+
switch (direction) {
|
|
30
|
+
case top$1:
|
|
31
|
+
scaleY = topScale;
|
|
32
|
+
if (lockRatio)
|
|
33
|
+
scaleX = scaleY;
|
|
34
|
+
origin = { x: x + width / 2, y: y + height };
|
|
35
|
+
break;
|
|
36
|
+
case right$2:
|
|
37
|
+
scaleX = rightScale;
|
|
38
|
+
if (lockRatio)
|
|
39
|
+
scaleY = scaleX;
|
|
40
|
+
origin = { x, y: y + height / 2 };
|
|
41
|
+
break;
|
|
42
|
+
case bottom$1:
|
|
43
|
+
scaleY = bottomScale;
|
|
44
|
+
if (lockRatio)
|
|
45
|
+
scaleX = scaleY;
|
|
46
|
+
origin = { x: x + width / 2, y };
|
|
47
|
+
break;
|
|
48
|
+
case left$2:
|
|
49
|
+
scaleX = leftScale;
|
|
50
|
+
if (lockRatio)
|
|
51
|
+
scaleY = scaleX;
|
|
52
|
+
origin = { x: x + width, y: y + height / 2 };
|
|
53
|
+
break;
|
|
54
|
+
case topLeft$1:
|
|
55
|
+
scaleY = topScale;
|
|
56
|
+
scaleX = leftScale;
|
|
57
|
+
if (lockRatio)
|
|
58
|
+
scaleX = scaleY;
|
|
59
|
+
origin = { x: x + width, y: y + height };
|
|
60
|
+
break;
|
|
61
|
+
case topRight$1:
|
|
62
|
+
scaleY = topScale;
|
|
63
|
+
scaleX = rightScale;
|
|
64
|
+
if (lockRatio)
|
|
65
|
+
scaleX = scaleY;
|
|
66
|
+
origin = { x, y: y + height };
|
|
67
|
+
break;
|
|
68
|
+
case bottomRight$1:
|
|
69
|
+
scaleY = bottomScale;
|
|
70
|
+
scaleX = rightScale;
|
|
71
|
+
if (lockRatio)
|
|
72
|
+
scaleX = scaleY;
|
|
73
|
+
origin = { x, y };
|
|
74
|
+
break;
|
|
75
|
+
case bottomLeft$1:
|
|
76
|
+
scaleY = bottomScale;
|
|
77
|
+
scaleX = leftScale;
|
|
78
|
+
if (lockRatio)
|
|
79
|
+
scaleX = scaleY;
|
|
80
|
+
origin = { x: x + width, y };
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
if (around) {
|
|
84
|
+
if (typeof around === 'object') {
|
|
85
|
+
origin = { x: x + width / around.x, y: y + height / around.y };
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
origin = { x: x + width / 2, y: y + height / 2 };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
reset(matrix);
|
|
92
|
+
scaleOfOuter(matrix, origin, scaleX, scaleY);
|
|
93
|
+
const bounds = { x: old.x + matrix.e, y: old.y + matrix.f, width: width * scaleX, height: height * scaleY };
|
|
94
|
+
return { bounds, old, origin, scaleX, scaleY, direction, lockRatio, around, };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const { topLeft, top, topRight, right: right$1, bottomRight, bottom, bottomLeft, left: left$1 } = IDirection8;
|
|
98
|
+
function updateCursor(editor, e) {
|
|
99
|
+
const point = editor.enterPoint;
|
|
100
|
+
if (!point || !editor.target || !editor.visible)
|
|
101
|
+
return;
|
|
102
|
+
let { rotation } = editor;
|
|
103
|
+
let { resizeCursor, rotateCursor, resizeable } = editor.config;
|
|
104
|
+
const mirror = editor.tool.getMirrorData(editor);
|
|
105
|
+
const { __direction, __isResizePoint } = point.__;
|
|
106
|
+
editor.enterPoint = point;
|
|
107
|
+
if (__isResizePoint && (e.metaKey || e.ctrlKey || !resizeable))
|
|
108
|
+
resizeCursor = rotateCursor;
|
|
109
|
+
if (mirror.x || mirror.y) {
|
|
110
|
+
mirrorCursors(resizeCursor = [...resizeCursor], mirror.x, mirror.y);
|
|
111
|
+
mirrorCursors(rotateCursor = [...rotateCursor], mirror.y, mirror.x);
|
|
112
|
+
if (mirror.x + mirror.y === 1)
|
|
113
|
+
rotation = -rotation;
|
|
114
|
+
}
|
|
115
|
+
let index = (__direction + Math.round(rotation / 45)) % 8;
|
|
116
|
+
if (index < 0)
|
|
117
|
+
index += 8;
|
|
118
|
+
point.cursor = __isResizePoint ? resizeCursor[index] : rotateCursor[index];
|
|
119
|
+
}
|
|
120
|
+
function mirrorCursors(mirror, mirrorX, mirrorY) {
|
|
121
|
+
if (mirrorX) {
|
|
122
|
+
const topCursor = mirror[top], topLeftCursor = mirror[topLeft], topRightCursor = mirror[topRight];
|
|
123
|
+
mirror[top] = mirror[bottom];
|
|
124
|
+
mirror[topLeft] = mirror[bottomLeft];
|
|
125
|
+
mirror[topRight] = mirror[bottomRight];
|
|
126
|
+
mirror[bottom] = topCursor;
|
|
127
|
+
mirror[bottomLeft] = topLeftCursor;
|
|
128
|
+
mirror[bottomRight] = topRightCursor;
|
|
129
|
+
}
|
|
130
|
+
if (mirrorY) {
|
|
131
|
+
const leftCursor = mirror[left$1], topLeftCursor = mirror[topLeft], bottomLeftCursor = mirror[bottomLeft];
|
|
132
|
+
mirror[left$1] = mirror[right$1];
|
|
133
|
+
mirror[topLeft] = mirror[topRight];
|
|
134
|
+
mirror[bottomLeft] = mirror[bottomRight];
|
|
135
|
+
mirror[right$1] = leftCursor;
|
|
136
|
+
mirror[topRight] = topLeftCursor;
|
|
137
|
+
mirror[bottomRight] = bottomLeftCursor;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const RectTool = {
|
|
142
|
+
name: 'RectTool',
|
|
143
|
+
getMirrorData(editor) {
|
|
144
|
+
const { scaleX, scaleY } = editor.target;
|
|
145
|
+
return {
|
|
146
|
+
x: scaleX < 0 ? 1 : 0,
|
|
147
|
+
y: scaleY < 0 ? 1 : 0
|
|
148
|
+
};
|
|
149
|
+
},
|
|
150
|
+
resize(e) {
|
|
151
|
+
const { target, bounds, resizeType, old } = e;
|
|
152
|
+
const { x, y, width, height } = bounds;
|
|
153
|
+
const point = { x: x - old.x, y: y - old.y };
|
|
154
|
+
target.innerToWorld(point, null, true, target.parent);
|
|
155
|
+
target.x += point.x;
|
|
156
|
+
target.y += point.y;
|
|
157
|
+
if (resizeType === 'scale') {
|
|
158
|
+
target.scaleX *= width / old.width;
|
|
159
|
+
target.scaleY *= height / old.height;
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
if (width < 0) {
|
|
163
|
+
target.width = -width;
|
|
164
|
+
target.scaleX *= -1;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
if (target.width !== width)
|
|
168
|
+
target.width = width;
|
|
169
|
+
}
|
|
170
|
+
if (height < 0) {
|
|
171
|
+
target.height = -height;
|
|
172
|
+
target.scaleY *= -1;
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
if (target.height !== height)
|
|
176
|
+
target.height = height;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
rotate(e) {
|
|
181
|
+
const { target, rotation, origin } = e;
|
|
182
|
+
target.rotateOf(origin, rotation);
|
|
183
|
+
},
|
|
184
|
+
update(editor) {
|
|
185
|
+
const { target, config, rotatePoints, targetRect, rect, circle, resizeLines, resizePoints } = editor;
|
|
186
|
+
const { type, resizeable, rotateable, stroke, pointFill, pointSize, pointRadius } = config;
|
|
187
|
+
const defaultStyle = { fill: pointFill, stroke, width: pointSize, height: pointSize, cornerRadius: pointRadius };
|
|
188
|
+
const pointStyles = config.point instanceof Array ? config.point : [config.point || defaultStyle];
|
|
189
|
+
const box = new Bounds(target.boxBounds);
|
|
190
|
+
const w = target.worldTransform, pw = editor.parent.worldTransform;
|
|
191
|
+
const matrix = new Matrix(w);
|
|
192
|
+
matrix.divide(pw);
|
|
193
|
+
const worldX = matrix.e, worldY = matrix.f;
|
|
194
|
+
let { scaleX, scaleY, rotation, skewX, skewY } = w;
|
|
195
|
+
scaleX /= pw.scaleX, scaleY /= pw.scaleY, rotation -= pw.rotation, skewX -= pw.skewX, skewY -= pw.skewY;
|
|
196
|
+
const { x, y, width, height } = box.scale(scaleX, scaleY);
|
|
197
|
+
editor.set({ x: worldX, y: worldY, rotation, skewX, skewY });
|
|
198
|
+
targetRect.set({ x, y, width: box.width / scaleX, height: box.height / scaleY, scaleX, scaleY, visible: true });
|
|
199
|
+
const points = [
|
|
200
|
+
{ x, y },
|
|
201
|
+
{ x: x + width / 2, y },
|
|
202
|
+
{ x: x + width, y },
|
|
203
|
+
{ x: x + width, y: y + height / 2 },
|
|
204
|
+
{ x: x + width, y: y + height },
|
|
205
|
+
{ x: x + width / 2, y: y + height },
|
|
206
|
+
{ x, y: y + height },
|
|
207
|
+
{ x, y: y + height / 2 }
|
|
208
|
+
];
|
|
209
|
+
const rectPoints = [];
|
|
210
|
+
let point, style, rotateP, resizeP, resizeL;
|
|
211
|
+
for (let i = 0; i < 8; i++) {
|
|
212
|
+
point = points[i];
|
|
213
|
+
style = pointStyles[i % pointStyles.length];
|
|
214
|
+
resizeP = resizePoints[i];
|
|
215
|
+
resizeL = resizeLines[Math.floor(i / 2)];
|
|
216
|
+
rotateP = rotatePoints[i];
|
|
217
|
+
resizeP.set(style);
|
|
218
|
+
resizeP.x = rotateP.x = resizeL.x = point.x;
|
|
219
|
+
resizeP.y = rotateP.y = resizeL.y = point.y;
|
|
220
|
+
resizeP.visible = resizeL.visible = resizeable || rotateable;
|
|
221
|
+
rotateP.visible = rotateable && resizeable;
|
|
222
|
+
if (i % 2) {
|
|
223
|
+
if (((i + 1) / 2) % 2) {
|
|
224
|
+
resizeL.width = Math.abs(width);
|
|
225
|
+
rotateP.width = Math.max(10, Math.abs(width) - 30);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
resizeL.height = Math.abs(height);
|
|
229
|
+
rotateP.height = Math.max(10, Math.abs(height) - 30);
|
|
230
|
+
}
|
|
231
|
+
resizeP.rotation = 90;
|
|
232
|
+
resizeP.visible = type === 'mobile';
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
rectPoints.push(point.x, point.y);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
style = config.rotatePoint || style;
|
|
239
|
+
circle.set(style);
|
|
240
|
+
circle.x = x + width / 2;
|
|
241
|
+
if (!style.y)
|
|
242
|
+
circle.y = y - (10 + (resizeP.height + circle.height) / 2) * (this.getMirrorData(editor).y ? -1 : 1);
|
|
243
|
+
circle.visible = rotateable && type === 'mobile';
|
|
244
|
+
rect.set(config.rect || { stroke });
|
|
245
|
+
rect.points = rectPoints;
|
|
246
|
+
rect.visible = true;
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const { left, right } = IDirection8;
|
|
251
|
+
const LineTool = {
|
|
252
|
+
name: 'LineTool',
|
|
253
|
+
getMirrorData(_editor) {
|
|
254
|
+
return {
|
|
255
|
+
x: 0,
|
|
256
|
+
y: 0
|
|
257
|
+
};
|
|
258
|
+
},
|
|
259
|
+
resize(e) {
|
|
260
|
+
const { direction, dragEvent, lockRatio, around } = e;
|
|
261
|
+
const target = e.target;
|
|
262
|
+
const fromPoint = { x: 0, y: 0 };
|
|
263
|
+
const { toPoint } = target;
|
|
264
|
+
target.rotation = 0;
|
|
265
|
+
let { x, y } = dragEvent.getInnerMove(target);
|
|
266
|
+
if (lockRatio) {
|
|
267
|
+
if (Math.abs(x) > Math.abs(y)) {
|
|
268
|
+
y = 0;
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
x = 0;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (direction === left) {
|
|
275
|
+
fromPoint.x += x;
|
|
276
|
+
fromPoint.y += y;
|
|
277
|
+
if (around) {
|
|
278
|
+
toPoint.x -= x;
|
|
279
|
+
toPoint.y -= y;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
if (around) {
|
|
284
|
+
fromPoint.x -= x;
|
|
285
|
+
fromPoint.y -= y;
|
|
286
|
+
}
|
|
287
|
+
toPoint.x += x;
|
|
288
|
+
toPoint.y += y;
|
|
289
|
+
}
|
|
290
|
+
target.getLocalPointByInner(fromPoint, null, null, true);
|
|
291
|
+
target.getLocalPointByInner(toPoint, null, null, true);
|
|
292
|
+
target.x = fromPoint.x;
|
|
293
|
+
target.y = fromPoint.y;
|
|
294
|
+
target.getInnerPointByLocal(toPoint, null, null, true);
|
|
295
|
+
target.toPoint = toPoint;
|
|
296
|
+
},
|
|
297
|
+
rotate(e) {
|
|
298
|
+
RectTool.rotate(e);
|
|
299
|
+
},
|
|
300
|
+
update(editor) {
|
|
301
|
+
const { rotatePoints, circle, resizeLines, resizePoints } = editor;
|
|
302
|
+
RectTool.update(editor);
|
|
303
|
+
for (let i = 0; i < 8; i++) {
|
|
304
|
+
if (i < 4)
|
|
305
|
+
resizeLines[i].visible = false;
|
|
306
|
+
resizePoints[i].visible = rotatePoints[i].visible = i === left || i === right;
|
|
307
|
+
}
|
|
308
|
+
circle.visible = false;
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
class EditorResizeEvent extends Event {
|
|
313
|
+
constructor(type, data) {
|
|
314
|
+
super(type);
|
|
315
|
+
if (data)
|
|
316
|
+
Object.assign(this, data);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
EditorResizeEvent.RESIZE = 'editor.resize';
|
|
320
|
+
|
|
321
|
+
class EditorRotateEvent extends Event {
|
|
322
|
+
constructor(type, data) {
|
|
323
|
+
super(type);
|
|
324
|
+
if (data)
|
|
325
|
+
Object.assign(this, data);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
EditorRotateEvent.ROTATE = 'editor.rotate';
|
|
329
|
+
|
|
330
|
+
class Editor extends Group {
|
|
331
|
+
get target() { return this._target; }
|
|
332
|
+
set target(value) {
|
|
333
|
+
this.__removeTargetEvents();
|
|
334
|
+
this.visible = !!value;
|
|
335
|
+
this._target = value;
|
|
336
|
+
if (value)
|
|
337
|
+
this.onTarget();
|
|
338
|
+
}
|
|
339
|
+
constructor(userConfig, data) {
|
|
340
|
+
super(data);
|
|
341
|
+
this.config = {
|
|
342
|
+
type: 'pc',
|
|
343
|
+
stroke: '#836DFF',
|
|
344
|
+
pointFill: '#FFFFFF',
|
|
345
|
+
pointSize: 10,
|
|
346
|
+
pointRadius: 10,
|
|
347
|
+
rotateGap: 90,
|
|
348
|
+
hideOnMove: false,
|
|
349
|
+
moveCursor: 'move',
|
|
350
|
+
resizeType: 'auto',
|
|
351
|
+
resizeCursor: ['nwse-resize', 'ns-resize', 'nesw-resize', 'ew-resize', 'nwse-resize', 'ns-resize', 'nesw-resize', 'ew-resize'],
|
|
352
|
+
rotateCursor: ['ne-resize', 'e-resize', 'se-resize', 's-resize', 'sw-resize', 'w-resize', 'nw-resize', 'n-resize'],
|
|
353
|
+
resizeable: true,
|
|
354
|
+
rotateable: true
|
|
355
|
+
};
|
|
356
|
+
this.resizePoints = [];
|
|
357
|
+
this.rotatePoints = [];
|
|
358
|
+
this.resizeLines = [];
|
|
359
|
+
this.targetRect = new Rect({ hitFill: 'all', hitRadius: 5 });
|
|
360
|
+
this.rect = new Polygon({ hittable: false, strokeAlign: 'center' });
|
|
361
|
+
this.circle = new Rect({ around: 'center', hitRadius: 10 });
|
|
362
|
+
this.__eventIds = [];
|
|
363
|
+
this.__targetEventIds = [];
|
|
364
|
+
if (userConfig)
|
|
365
|
+
this.config = DataHelper.default(userConfig, this.config);
|
|
366
|
+
this.init();
|
|
367
|
+
}
|
|
368
|
+
init() {
|
|
369
|
+
let rotatePoint, resizeLine, resizePoint;
|
|
370
|
+
const { resizePoints, rotatePoints, resizeLines } = this;
|
|
371
|
+
for (let i = 0; i < 8; i++) {
|
|
372
|
+
rotatePoint = new Rect({ around: 'center', width: 30, height: 30, hitRadius: 10, hitFill: "all" });
|
|
373
|
+
rotatePoints.push(rotatePoint);
|
|
374
|
+
this.__listenPointEvents(rotatePoint, 'rotate', i);
|
|
375
|
+
if (i % 2) {
|
|
376
|
+
resizeLine = new Rect({ around: 'center', width: 10, height: 10, hitFill: "all" });
|
|
377
|
+
resizeLines.push(resizeLine);
|
|
378
|
+
this.__listenPointEvents(resizeLine, 'resize', i);
|
|
379
|
+
}
|
|
380
|
+
resizePoint = new Rect({ around: 'center', hitRadius: 5 });
|
|
381
|
+
resizePoints.push(resizePoint);
|
|
382
|
+
this.__listenPointEvents(resizePoint, 'resize', i);
|
|
383
|
+
}
|
|
384
|
+
this.__listenPointEvents(this.circle, 'rotate', 1);
|
|
385
|
+
this.addMany(...rotatePoints, this.targetRect, this.rect, this.circle, ...resizeLines, ...resizePoints);
|
|
386
|
+
this.__listenEvents();
|
|
387
|
+
}
|
|
388
|
+
onTarget() {
|
|
389
|
+
this.tool = this.getTool(this.target);
|
|
390
|
+
this.waitLeafer(() => {
|
|
391
|
+
this.update();
|
|
392
|
+
this.updateMoveCursor();
|
|
393
|
+
this.__listenTargetEvents();
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
getTool(value) {
|
|
397
|
+
return (value.tag === 'Line' && value.resizeable) ? LineTool : RectTool;
|
|
398
|
+
}
|
|
399
|
+
update() {
|
|
400
|
+
if (!this.target)
|
|
401
|
+
return;
|
|
402
|
+
this.tool.update(this);
|
|
403
|
+
}
|
|
404
|
+
onDrag(e) {
|
|
405
|
+
const { resizeable, rotateable } = this.config;
|
|
406
|
+
if (e.metaKey || e.ctrlKey || !resizeable) {
|
|
407
|
+
if (rotateable)
|
|
408
|
+
this.onRotate(e);
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
this.onResize(e);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
onMove(e) {
|
|
415
|
+
const { target } = this;
|
|
416
|
+
const { x, y } = e.getLocalMove(target);
|
|
417
|
+
if (e.shiftKey) {
|
|
418
|
+
if (Math.abs(x) > Math.abs(y)) {
|
|
419
|
+
target.x += x;
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
target.y += y;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
target.x += x;
|
|
427
|
+
target.y += y;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
onRotate(e) {
|
|
431
|
+
const { target } = this;
|
|
432
|
+
const { rotateGap } = this.config;
|
|
433
|
+
const { x, y, width, height } = target.boxBounds;
|
|
434
|
+
const origin = { x: x + width / 2, y: y + height / 2 };
|
|
435
|
+
let rotation;
|
|
436
|
+
if (e instanceof RotateEvent) {
|
|
437
|
+
rotation = e.rotation;
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
440
|
+
const point = e;
|
|
441
|
+
const last = { x: point.x - e.moveX, y: point.y - e.moveY };
|
|
442
|
+
rotation = PointHelper.getChangeAngle(last, target.getWorldPoint(origin), point);
|
|
443
|
+
}
|
|
444
|
+
rotation = MathHelper.getGapRotation(target.rotation + rotation, rotateGap) - target.rotation;
|
|
445
|
+
const event = new EditorRotateEvent(EditorRotateEvent.ROTATE, { editor: this, target, origin, rotation });
|
|
446
|
+
this.tool.rotate(event);
|
|
447
|
+
target.emitEvent(event);
|
|
448
|
+
}
|
|
449
|
+
onResize(e) {
|
|
450
|
+
const { target } = this;
|
|
451
|
+
const { __direction } = e.current.__;
|
|
452
|
+
let { resizeType, around, lockRatio } = this.config;
|
|
453
|
+
if (e.shiftKey)
|
|
454
|
+
lockRatio = true;
|
|
455
|
+
if (e.altKey && !around)
|
|
456
|
+
around = 'center';
|
|
457
|
+
if (resizeType === 'auto')
|
|
458
|
+
resizeType = target.resizeable ? 'size' : 'scale';
|
|
459
|
+
const data = getResizeData(target.boxBounds, __direction, e.getInnerMove(this.targetRect), lockRatio, around);
|
|
460
|
+
const event = new EditorResizeEvent(EditorResizeEvent.RESIZE, Object.assign(Object.assign({}, data), { target, editor: this, dragEvent: e, resizeType }));
|
|
461
|
+
this.tool.resize(event);
|
|
462
|
+
target.emitEvent(event);
|
|
463
|
+
}
|
|
464
|
+
updateMoveCursor() {
|
|
465
|
+
this.targetRect.cursor = this.config.moveCursor;
|
|
466
|
+
}
|
|
467
|
+
__listenEvents() {
|
|
468
|
+
this.__eventIds = [
|
|
469
|
+
this.targetRect.on_(DragEvent.START, () => { this.opacity = this.config.hideOnMove ? 0 : 1; }),
|
|
470
|
+
this.targetRect.on_(DragEvent.DRAG, this.onMove, this),
|
|
471
|
+
this.targetRect.on_(DragEvent.END, () => { this.opacity = 1; }),
|
|
472
|
+
this.targetRect.on_(PointerEvent.ENTER, this.updateMoveCursor, this)
|
|
473
|
+
];
|
|
474
|
+
}
|
|
475
|
+
__removeListenEvents() {
|
|
476
|
+
this.targetRect.off_(this.__eventIds);
|
|
477
|
+
this.__eventIds.length = 0;
|
|
478
|
+
}
|
|
479
|
+
__listenPointEvents(point, type, direction) {
|
|
480
|
+
point.__.__direction = direction;
|
|
481
|
+
const resize = point.__.__isResizePoint = type === 'resize';
|
|
482
|
+
point.on_(DragEvent.DRAG, resize ? this.onDrag : this.onRotate, this);
|
|
483
|
+
point.on_(PointerEvent.LEAVE, () => this.enterPoint = null);
|
|
484
|
+
point.on_(PointerEvent.ENTER, (e) => { this.enterPoint = point; updateCursor(this, e); });
|
|
485
|
+
}
|
|
486
|
+
__listenTargetEvents() {
|
|
487
|
+
if (this.target) {
|
|
488
|
+
const { leafer } = this.target;
|
|
489
|
+
this.__targetEventIds = [
|
|
490
|
+
leafer.on_(RenderEvent.START, this.update, this),
|
|
491
|
+
leafer.on_([KeyEvent.HOLD, KeyEvent.UP], (e) => { updateCursor(this, e); })
|
|
492
|
+
];
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
__removeTargetEvents() {
|
|
496
|
+
if (this.__targetEventIds.length) {
|
|
497
|
+
const { leafer } = this.target;
|
|
498
|
+
if (leafer)
|
|
499
|
+
leafer.off_(this.__targetEventIds);
|
|
500
|
+
this.__targetEventIds.length = 0;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
destroy() {
|
|
504
|
+
this.__removeListenEvents();
|
|
505
|
+
this._target = null;
|
|
506
|
+
super.destroy();
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
export { Editor, EditorResizeEvent, EditorRotateEvent, LineTool, RectTool };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{MatrixHelper as t,Bounds as e,Matrix as i,Event as s,Group as o,Rect as r,Polygon as n,DataHelper as a,RotateEvent as h,PointHelper as l,MathHelper as c,DragEvent as g,PointerEvent as y,RenderEvent as d,KeyEvent as u}from"@leafer-ui/core";var _;!function(t){t[t.topLeft=0]="topLeft",t[t.top=1]="top",t[t.topRight=2]="topRight",t[t.right=3]="right",t[t.bottomRight=4]="bottomRight",t[t.bottom=5]="bottom",t[t.bottomLeft=6]="bottomLeft",t[t.left=7]="left"}(_||(_={}));const{scaleOfOuter:x,reset:b}=t,{topLeft:v,top:f,topRight:p,right:z,bottomRight:R,bottom:w,bottomLeft:m,left:E}=_,M={};const{topLeft:P,top:T,topRight:L,right:k,bottomRight:I,bottom:F,bottomLeft:O,left:D}=_;function X(t,e){const i=t.enterPoint;if(!i||!t.target||!t.visible)return;let{rotation:s}=t,{resizeCursor:o,rotateCursor:r,resizeable:n}=t.config;const a=t.tool.getMirrorData(t),{__direction:h,__isResizePoint:l}=i.__;t.enterPoint=i,l&&(e.metaKey||e.ctrlKey||!n)&&(o=r),(a.x||a.y)&&(Y(o=[...o],a.x,a.y),Y(r=[...r],a.y,a.x),a.x+a.y===1&&(s=-s));let c=(h+Math.round(s/45))%8;c<0&&(c+=8),i.cursor=l?o[c]:r[c]}function Y(t,e,i){if(e){const e=t[T],i=t[P],s=t[L];t[T]=t[F],t[P]=t[O],t[L]=t[I],t[F]=e,t[O]=i,t[I]=s}if(i){const e=t[D],i=t[P],s=t[O];t[D]=t[k],t[P]=t[L],t[O]=t[I],t[k]=e,t[L]=i,t[I]=s}}const A={name:"RectTool",getMirrorData(t){const{scaleX:e,scaleY:i}=t.target;return{x:e<0?1:0,y:i<0?1:0}},resize(t){const{target:e,bounds:i,resizeType:s,old:o}=t,{x:r,y:n,width:a,height:h}=i,l={x:r-o.x,y:n-o.y};e.innerToWorld(l,null,!0,e.parent),e.x+=l.x,e.y+=l.y,"scale"===s?(e.scaleX*=a/o.width,e.scaleY*=h/o.height):(a<0?(e.width=-a,e.scaleX*=-1):e.width!==a&&(e.width=a),h<0?(e.height=-h,e.scaleY*=-1):e.height!==h&&(e.height=h))},rotate(t){const{target:e,rotation:i,origin:s}=t;e.rotateOf(s,i)},update(t){const{target:s,config:o,rotatePoints:r,targetRect:n,rect:a,circle:h,resizeLines:l,resizePoints:c}=t,{type:g,resizeable:y,rotateable:d,stroke:u,pointFill:_,pointSize:x,pointRadius:b}=o,v={fill:_,stroke:u,width:x,height:x,cornerRadius:b},f=o.point instanceof Array?o.point:[o.point||v],p=new e(s.boxBounds),z=s.worldTransform,R=t.parent.worldTransform,w=new i(z);w.divide(R);const m=w.e,E=w.f;let{scaleX:M,scaleY:P,rotation:T,skewX:L,skewY:k}=z;M/=R.scaleX,P/=R.scaleY,T-=R.rotation,L-=R.skewX,k-=R.skewY;const{x:I,y:F,width:O,height:D}=p.scale(M,P);t.set({x:m,y:E,rotation:T,skewX:L,skewY:k}),n.set({x:I,y:F,width:p.width/M,height:p.height/P,scaleX:M,scaleY:P,visible:!0});const X=[{x:I,y:F},{x:I+O/2,y:F},{x:I+O,y:F},{x:I+O,y:F+D/2},{x:I+O,y:F+D},{x:I+O/2,y:F+D},{x:I,y:F+D},{x:I,y:F+D/2}],Y=[];let A,C,K,B,S;for(let t=0;t<8;t++)A=X[t],C=f[t%f.length],B=c[t],S=l[Math.floor(t/2)],K=r[t],B.set(C),B.x=K.x=S.x=A.x,B.y=K.y=S.y=A.y,B.visible=S.visible=y||d,K.visible=d&&y,t%2?((t+1)/2%2?(S.width=Math.abs(O),K.width=Math.max(10,Math.abs(O)-30)):(S.height=Math.abs(D),K.height=Math.max(10,Math.abs(D)-30)),B.rotation=90,B.visible="mobile"===g):Y.push(A.x,A.y);C=o.rotatePoint||C,h.set(C),h.x=I+O/2,C.y||(h.y=F-(10+(B.height+h.height)/2)*(this.getMirrorData(t).y?-1:1)),h.visible=d&&"mobile"===g,a.set(o.rect||{stroke:u}),a.points=Y,a.visible=!0}},{left:C,right:K}=_,B={name:"LineTool",getMirrorData:t=>({x:0,y:0}),resize(t){const{direction:e,dragEvent:i,lockRatio:s,around:o}=t,r=t.target,n={x:0,y:0},{toPoint:a}=r;r.rotation=0;let{x:h,y:l}=i.getInnerMove(r);s&&(Math.abs(h)>Math.abs(l)?l=0:h=0),e===C?(n.x+=h,n.y+=l,o&&(a.x-=h,a.y-=l)):(o&&(n.x-=h,n.y-=l),a.x+=h,a.y+=l),r.getLocalPointByInner(n,null,null,!0),r.getLocalPointByInner(a,null,null,!0),r.x=n.x,r.y=n.y,r.getInnerPointByLocal(a,null,null,!0),r.toPoint=a},rotate(t){A.rotate(t)},update(t){const{rotatePoints:e,circle:i,resizeLines:s,resizePoints:o}=t;A.update(t);for(let t=0;t<8;t++)t<4&&(s[t].visible=!1),o[t].visible=e[t].visible=t===C||t===K;i.visible=!1}};class S extends s{constructor(t,e){super(t),e&&Object.assign(this,e)}}S.RESIZE="editor.resize";class j extends s{constructor(t,e){super(t),e&&Object.assign(this,e)}}j.ROTATE="editor.rotate";class G extends o{get target(){return this._target}set target(t){this.__removeTargetEvents(),this.visible=!!t,this._target=t,t&&this.onTarget()}constructor(t,e){super(e),this.config={type:"pc",stroke:"#836DFF",pointFill:"#FFFFFF",pointSize:10,pointRadius:10,rotateGap:90,hideOnMove:!1,moveCursor:"move",resizeType:"auto",resizeCursor:["nwse-resize","ns-resize","nesw-resize","ew-resize","nwse-resize","ns-resize","nesw-resize","ew-resize"],rotateCursor:["ne-resize","e-resize","se-resize","s-resize","sw-resize","w-resize","nw-resize","n-resize"],resizeable:!0,rotateable:!0},this.resizePoints=[],this.rotatePoints=[],this.resizeLines=[],this.targetRect=new r({hitFill:"all",hitRadius:5}),this.rect=new n({hittable:!1,strokeAlign:"center"}),this.circle=new r({around:"center",hitRadius:10}),this.__eventIds=[],this.__targetEventIds=[],t&&(this.config=a.default(t,this.config)),this.init()}init(){let t,e,i;const{resizePoints:s,rotatePoints:o,resizeLines:n}=this;for(let a=0;a<8;a++)t=new r({around:"center",width:30,height:30,hitRadius:10,hitFill:"all"}),o.push(t),this.__listenPointEvents(t,"rotate",a),a%2&&(e=new r({around:"center",width:10,height:10,hitFill:"all"}),n.push(e),this.__listenPointEvents(e,"resize",a)),i=new r({around:"center",hitRadius:5}),s.push(i),this.__listenPointEvents(i,"resize",a);this.__listenPointEvents(this.circle,"rotate",1),this.addMany(...o,this.targetRect,this.rect,this.circle,...n,...s),this.__listenEvents()}onTarget(){this.tool=this.getTool(this.target),this.waitLeafer((()=>{this.update(),this.updateMoveCursor(),this.__listenTargetEvents()}))}getTool(t){return"Line"===t.tag&&t.resizeable?B:A}update(){this.target&&this.tool.update(this)}onDrag(t){const{resizeable:e,rotateable:i}=this.config;t.metaKey||t.ctrlKey||!e?i&&this.onRotate(t):this.onResize(t)}onMove(t){const{target:e}=this,{x:i,y:s}=t.getLocalMove(e);t.shiftKey?Math.abs(i)>Math.abs(s)?e.x+=i:e.y+=s:(e.x+=i,e.y+=s)}onRotate(t){const{target:e}=this,{rotateGap:i}=this.config,{x:s,y:o,width:r,height:n}=e.boxBounds,a={x:s+r/2,y:o+n/2};let g;if(t instanceof h)g=t.rotation;else{const i=t,s={x:i.x-t.moveX,y:i.y-t.moveY};g=l.getChangeAngle(s,e.getWorldPoint(a),i)}g=c.getGapRotation(e.rotation+g,i)-e.rotation;const y=new j(j.ROTATE,{editor:this,target:e,origin:a,rotation:g});this.tool.rotate(y),e.emitEvent(y)}onResize(t){const{target:e}=this,{__direction:i}=t.current.__;let{resizeType:s,around:o,lockRatio:r}=this.config;t.shiftKey&&(r=!0),t.altKey&&!o&&(o="center"),"auto"===s&&(s=e.resizeable?"size":"scale");const n=function(t,e,i,s,o){o&&(i.x*=2,i.y*=2);let r,n=1,a=1;const{x:h,y:l,width:c,height:g}=t,y=(-i.y+g)/g,d=(i.x+c)/c,u=(i.y+g)/g,_=(-i.x+c)/c;switch(e){case f:a=y,s&&(n=a),r={x:h+c/2,y:l+g};break;case z:n=d,s&&(a=n),r={x:h,y:l+g/2};break;case w:a=u,s&&(n=a),r={x:h+c/2,y:l};break;case E:n=_,s&&(a=n),r={x:h+c,y:l+g/2};break;case v:a=y,n=_,s&&(n=a),r={x:h+c,y:l+g};break;case p:a=y,n=d,s&&(n=a),r={x:h,y:l+g};break;case R:a=u,n=d,s&&(n=a),r={x:h,y:l};break;case m:a=u,n=_,s&&(n=a),r={x:h+c,y:l}}return o&&(r="object"==typeof o?{x:h+c/o.x,y:l+g/o.y}:{x:h+c/2,y:l+g/2}),b(M),x(M,r,n,a),{bounds:{x:t.x+M.e,y:t.y+M.f,width:c*n,height:g*a},old:t,origin:r,scaleX:n,scaleY:a,direction:e,lockRatio:s,around:o}}(e.boxBounds,i,t.getInnerMove(this.targetRect),r,o),a=new S(S.RESIZE,Object.assign(Object.assign({},n),{target:e,editor:this,dragEvent:t,resizeType:s}));this.tool.resize(a),e.emitEvent(a)}updateMoveCursor(){this.targetRect.cursor=this.config.moveCursor}__listenEvents(){this.__eventIds=[this.targetRect.on_(g.START,(()=>{this.opacity=this.config.hideOnMove?0:1})),this.targetRect.on_(g.DRAG,this.onMove,this),this.targetRect.on_(g.END,(()=>{this.opacity=1})),this.targetRect.on_(y.ENTER,this.updateMoveCursor,this)]}__removeListenEvents(){this.targetRect.off_(this.__eventIds),this.__eventIds.length=0}__listenPointEvents(t,e,i){t.__.__direction=i;const s=t.__.__isResizePoint="resize"===e;t.on_(g.DRAG,s?this.onDrag:this.onRotate,this),t.on_(y.LEAVE,(()=>this.enterPoint=null)),t.on_(y.ENTER,(e=>{this.enterPoint=t,X(this,e)}))}__listenTargetEvents(){if(this.target){const{leafer:t}=this.target;this.__targetEventIds=[t.on_(d.START,this.update,this),t.on_([u.HOLD,u.UP],(t=>{X(this,t)}))]}}__removeTargetEvents(){if(this.__targetEventIds.length){const{leafer:t}=this.target;t&&t.off_(this.__targetEventIds),this.__targetEventIds.length=0}}destroy(){this.__removeListenEvents(),this._target=null,super.destroy()}}export{G as Editor,S as EditorResizeEvent,j as EditorRotateEvent,B as LineTool,A as RectTool};
|