@idraw/util 0.3.0 → 0.4.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/index.d.ts +26 -71
- package/dist/esm/index.js +26 -29
- package/dist/esm/lib/canvas.d.ts +15 -0
- package/dist/esm/lib/canvas.js +36 -0
- package/dist/esm/lib/check.d.ts +8 -8
- package/dist/esm/lib/check.js +32 -33
- package/dist/esm/lib/color.d.ts +1 -0
- package/dist/esm/lib/color.js +152 -1
- package/dist/esm/lib/context2d.d.ts +75 -0
- package/dist/esm/lib/context2d.js +226 -0
- package/dist/esm/lib/controller.d.ts +6 -0
- package/dist/esm/lib/controller.js +99 -0
- package/dist/esm/lib/data.d.ts +5 -1
- package/dist/esm/lib/data.js +67 -2
- package/dist/esm/lib/element.d.ts +18 -0
- package/dist/esm/lib/element.js +241 -0
- package/dist/esm/lib/event.d.ts +9 -0
- package/dist/esm/lib/event.js +50 -0
- package/dist/esm/lib/html.d.ts +3 -0
- package/dist/esm/lib/html.js +170 -0
- package/dist/esm/lib/image.d.ts +4 -0
- package/dist/esm/lib/image.js +27 -0
- package/dist/esm/lib/is.d.ts +4 -2
- package/dist/esm/lib/is.js +34 -15
- package/dist/esm/lib/istype.d.ts +1 -2
- package/dist/esm/lib/istype.js +3 -4
- package/dist/esm/lib/{loader.js → load.js} +2 -2
- package/dist/esm/lib/middleware.d.ts +3 -0
- package/dist/esm/lib/middleware.js +22 -0
- package/dist/esm/lib/number.d.ts +3 -0
- package/dist/esm/lib/number.js +4 -0
- package/dist/esm/lib/parser.js +4 -1
- package/dist/esm/lib/point.d.ts +8 -0
- package/dist/esm/lib/point.js +30 -0
- package/dist/esm/lib/rect.d.ts +2 -0
- package/dist/esm/lib/rect.js +11 -0
- package/dist/esm/lib/rotate.d.ts +13 -0
- package/dist/esm/lib/rotate.js +205 -0
- package/dist/esm/lib/store.d.ts +12 -0
- package/dist/esm/lib/store.js +22 -0
- package/dist/esm/lib/svg-path.d.ts +10 -0
- package/dist/esm/lib/svg-path.js +36 -0
- package/dist/esm/lib/uuid.d.ts +2 -0
- package/dist/esm/lib/uuid.js +27 -2
- package/dist/esm/lib/vertex.d.ts +10 -0
- package/dist/esm/lib/vertex.js +73 -0
- package/dist/esm/lib/view-calc.d.ts +49 -0
- package/dist/esm/lib/view-calc.js +167 -0
- package/dist/index.global.js +1706 -330
- package/dist/index.global.min.js +1 -1
- package/package.json +4 -4
- package/LICENSE +0 -21
- package/dist/esm/lib/context.d.ts +0 -80
- package/dist/esm/lib/context.js +0 -194
- /package/dist/esm/lib/{loader.d.ts → load.d.ts} +0 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
export class Context2D {
|
|
2
|
+
constructor(ctx, opts) {
|
|
3
|
+
this._devicePixelRatio = 1;
|
|
4
|
+
const { devicePixelRatio = 1 } = opts;
|
|
5
|
+
this._ctx = ctx;
|
|
6
|
+
this._devicePixelRatio = devicePixelRatio;
|
|
7
|
+
}
|
|
8
|
+
$undoPixelRatio(num) {
|
|
9
|
+
return num / this._devicePixelRatio;
|
|
10
|
+
}
|
|
11
|
+
$doPixelRatio(num) {
|
|
12
|
+
return this._devicePixelRatio * num;
|
|
13
|
+
}
|
|
14
|
+
$getContext() {
|
|
15
|
+
return this._ctx;
|
|
16
|
+
}
|
|
17
|
+
$setFont(opts) {
|
|
18
|
+
const strList = [];
|
|
19
|
+
if (opts.fontWeight) {
|
|
20
|
+
strList.push(`${opts.fontWeight}`);
|
|
21
|
+
}
|
|
22
|
+
strList.push(`${this.$doPixelRatio(opts.fontSize || 12)}px`);
|
|
23
|
+
strList.push(`${opts.fontFamily || 'sans-serif'}`);
|
|
24
|
+
this._ctx.font = `${strList.join(' ')}`;
|
|
25
|
+
}
|
|
26
|
+
$resize(opts) {
|
|
27
|
+
const { width, height, devicePixelRatio } = opts;
|
|
28
|
+
const { canvas } = this._ctx;
|
|
29
|
+
canvas.width = width * devicePixelRatio;
|
|
30
|
+
canvas.height = height * devicePixelRatio;
|
|
31
|
+
this._devicePixelRatio = devicePixelRatio;
|
|
32
|
+
}
|
|
33
|
+
get canvas() {
|
|
34
|
+
return this._ctx.canvas;
|
|
35
|
+
}
|
|
36
|
+
get fillStyle() {
|
|
37
|
+
return this._ctx.fillStyle;
|
|
38
|
+
}
|
|
39
|
+
set fillStyle(value) {
|
|
40
|
+
this._ctx.fillStyle = value;
|
|
41
|
+
}
|
|
42
|
+
get strokeStyle() {
|
|
43
|
+
return this._ctx.strokeStyle;
|
|
44
|
+
}
|
|
45
|
+
set strokeStyle(color) {
|
|
46
|
+
this._ctx.strokeStyle = color;
|
|
47
|
+
}
|
|
48
|
+
get lineWidth() {
|
|
49
|
+
return this.$undoPixelRatio(this._ctx.lineWidth);
|
|
50
|
+
}
|
|
51
|
+
set lineWidth(w) {
|
|
52
|
+
this._ctx.lineWidth = this.$doPixelRatio(w);
|
|
53
|
+
}
|
|
54
|
+
get textAlign() {
|
|
55
|
+
return this._ctx.textAlign;
|
|
56
|
+
}
|
|
57
|
+
set textAlign(align) {
|
|
58
|
+
this._ctx.textAlign = align;
|
|
59
|
+
}
|
|
60
|
+
get textBaseline() {
|
|
61
|
+
return this._ctx.textBaseline;
|
|
62
|
+
}
|
|
63
|
+
set textBaseline(baseline) {
|
|
64
|
+
this._ctx.textBaseline = baseline;
|
|
65
|
+
}
|
|
66
|
+
get globalAlpha() {
|
|
67
|
+
return this._ctx.globalAlpha;
|
|
68
|
+
}
|
|
69
|
+
set globalAlpha(alpha) {
|
|
70
|
+
this._ctx.globalAlpha = alpha;
|
|
71
|
+
}
|
|
72
|
+
get shadowColor() {
|
|
73
|
+
return this._ctx.shadowColor;
|
|
74
|
+
}
|
|
75
|
+
set shadowColor(color) {
|
|
76
|
+
this._ctx.shadowColor = color;
|
|
77
|
+
}
|
|
78
|
+
get shadowOffsetX() {
|
|
79
|
+
return this.$undoPixelRatio(this._ctx.shadowOffsetX);
|
|
80
|
+
}
|
|
81
|
+
set shadowOffsetX(offsetX) {
|
|
82
|
+
this._ctx.shadowOffsetX = this.$doPixelRatio(offsetX);
|
|
83
|
+
}
|
|
84
|
+
get shadowOffsetY() {
|
|
85
|
+
return this.$undoPixelRatio(this._ctx.shadowOffsetY);
|
|
86
|
+
}
|
|
87
|
+
set shadowOffsetY(offsetY) {
|
|
88
|
+
this._ctx.shadowOffsetY = this.$doPixelRatio(offsetY);
|
|
89
|
+
}
|
|
90
|
+
get shadowBlur() {
|
|
91
|
+
return this.$undoPixelRatio(this._ctx.shadowBlur);
|
|
92
|
+
}
|
|
93
|
+
set shadowBlur(blur) {
|
|
94
|
+
this._ctx.shadowBlur = this.$doPixelRatio(blur);
|
|
95
|
+
}
|
|
96
|
+
get lineCap() {
|
|
97
|
+
return this._ctx.lineCap;
|
|
98
|
+
}
|
|
99
|
+
set lineCap(lineCap) {
|
|
100
|
+
this._ctx.lineCap = lineCap;
|
|
101
|
+
}
|
|
102
|
+
get globalCompositeOperation() {
|
|
103
|
+
return this._ctx.globalCompositeOperation;
|
|
104
|
+
}
|
|
105
|
+
set globalCompositeOperation(operations) {
|
|
106
|
+
this._ctx.globalCompositeOperation = operations;
|
|
107
|
+
}
|
|
108
|
+
fill(...args) {
|
|
109
|
+
return this._ctx.fill(...args);
|
|
110
|
+
}
|
|
111
|
+
arc(x, y, radius, startAngle, endAngle, anticlockwise) {
|
|
112
|
+
return this._ctx.arc(this.$doPixelRatio(x), this.$doPixelRatio(y), this.$doPixelRatio(radius), startAngle, endAngle, anticlockwise);
|
|
113
|
+
}
|
|
114
|
+
rect(x, y, w, h) {
|
|
115
|
+
return this._ctx.rect(this.$doPixelRatio(x), this.$doPixelRatio(y), this.$doPixelRatio(w), this.$doPixelRatio(h));
|
|
116
|
+
}
|
|
117
|
+
fillRect(x, y, w, h) {
|
|
118
|
+
return this._ctx.fillRect(this.$doPixelRatio(x), this.$doPixelRatio(y), this.$doPixelRatio(w), this.$doPixelRatio(h));
|
|
119
|
+
}
|
|
120
|
+
clearRect(x, y, w, h) {
|
|
121
|
+
return this._ctx.clearRect(this.$doPixelRatio(x), this.$doPixelRatio(y), this.$doPixelRatio(w), this.$doPixelRatio(h));
|
|
122
|
+
}
|
|
123
|
+
beginPath() {
|
|
124
|
+
return this._ctx.beginPath();
|
|
125
|
+
}
|
|
126
|
+
closePath() {
|
|
127
|
+
return this._ctx.closePath();
|
|
128
|
+
}
|
|
129
|
+
lineTo(x, y) {
|
|
130
|
+
return this._ctx.lineTo(this.$doPixelRatio(x), this.$doPixelRatio(y));
|
|
131
|
+
}
|
|
132
|
+
moveTo(x, y) {
|
|
133
|
+
return this._ctx.moveTo(this.$doPixelRatio(x), this.$doPixelRatio(y));
|
|
134
|
+
}
|
|
135
|
+
arcTo(x1, y1, x2, y2, radius) {
|
|
136
|
+
return this._ctx.arcTo(this.$doPixelRatio(x1), this.$doPixelRatio(y1), this.$doPixelRatio(x2), this.$doPixelRatio(y2), this.$doPixelRatio(radius));
|
|
137
|
+
}
|
|
138
|
+
getLineDash() {
|
|
139
|
+
return this._ctx.getLineDash();
|
|
140
|
+
}
|
|
141
|
+
setLineDash(nums) {
|
|
142
|
+
return this._ctx.setLineDash(nums.map((n) => this.$doPixelRatio(n)));
|
|
143
|
+
}
|
|
144
|
+
stroke(path) {
|
|
145
|
+
return path ? this._ctx.stroke(path) : this._ctx.stroke();
|
|
146
|
+
}
|
|
147
|
+
translate(x, y) {
|
|
148
|
+
return this._ctx.translate(this.$doPixelRatio(x), this.$doPixelRatio(y));
|
|
149
|
+
}
|
|
150
|
+
rotate(angle) {
|
|
151
|
+
return this._ctx.rotate(angle);
|
|
152
|
+
}
|
|
153
|
+
drawImage(...args) {
|
|
154
|
+
const image = args[0];
|
|
155
|
+
const sx = args[1];
|
|
156
|
+
const sy = args[2];
|
|
157
|
+
const sw = args[3];
|
|
158
|
+
const sh = args[4];
|
|
159
|
+
const dx = args[args.length - 4];
|
|
160
|
+
const dy = args[args.length - 3];
|
|
161
|
+
const dw = args[args.length - 2];
|
|
162
|
+
const dh = args[args.length - 1];
|
|
163
|
+
if (args.length === 9) {
|
|
164
|
+
return this._ctx.drawImage(image, this.$doPixelRatio(sx), this.$doPixelRatio(sy), this.$doPixelRatio(sw), this.$doPixelRatio(sh), this.$doPixelRatio(dx), this.$doPixelRatio(dy), this.$doPixelRatio(dw), this.$doPixelRatio(dh));
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
return this._ctx.drawImage(image, this.$doPixelRatio(dx), this.$doPixelRatio(dy), this.$doPixelRatio(dw), this.$doPixelRatio(dh));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
createPattern(image, repetition) {
|
|
171
|
+
return this._ctx.createPattern(image, repetition);
|
|
172
|
+
}
|
|
173
|
+
measureText(text) {
|
|
174
|
+
const textMetrics = this._ctx.measureText(text);
|
|
175
|
+
return textMetrics;
|
|
176
|
+
}
|
|
177
|
+
fillText(text, x, y, maxWidth) {
|
|
178
|
+
if (maxWidth !== undefined) {
|
|
179
|
+
return this._ctx.fillText(text, this.$doPixelRatio(x), this.$doPixelRatio(y), this.$doPixelRatio(maxWidth));
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
return this._ctx.fillText(text, this.$doPixelRatio(x), this.$doPixelRatio(y));
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
strokeText(text, x, y, maxWidth) {
|
|
186
|
+
if (maxWidth !== undefined) {
|
|
187
|
+
return this._ctx.strokeText(text, this.$doPixelRatio(x), this.$doPixelRatio(y), this.$doPixelRatio(maxWidth));
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
return this._ctx.strokeText(text, this.$doPixelRatio(x), this.$doPixelRatio(y));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
save() {
|
|
194
|
+
this._ctx.save();
|
|
195
|
+
}
|
|
196
|
+
restore() {
|
|
197
|
+
this._ctx.restore();
|
|
198
|
+
}
|
|
199
|
+
scale(ratioX, ratioY) {
|
|
200
|
+
this._ctx.scale(ratioX, ratioY);
|
|
201
|
+
}
|
|
202
|
+
circle(x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise) {
|
|
203
|
+
this._ctx.ellipse(this.$doPixelRatio(x), this.$doPixelRatio(y), this.$doPixelRatio(radiusX), this.$doPixelRatio(radiusY), rotation, startAngle, endAngle, counterclockwise);
|
|
204
|
+
}
|
|
205
|
+
isPointInPath(x, y) {
|
|
206
|
+
return this._ctx.isPointInPath(this.$doPixelRatio(x), this.$doPixelRatio(y));
|
|
207
|
+
}
|
|
208
|
+
clip(...args) {
|
|
209
|
+
return this._ctx.clip(...args);
|
|
210
|
+
}
|
|
211
|
+
setTransform(a, b, c, d, e, f) {
|
|
212
|
+
return this._ctx.setTransform(a, b, c, d, e, f);
|
|
213
|
+
}
|
|
214
|
+
getTransform() {
|
|
215
|
+
return this._ctx.getTransform();
|
|
216
|
+
}
|
|
217
|
+
createLinearGradient(x0, y0, x1, y1) {
|
|
218
|
+
return this._ctx.createLinearGradient(this.$doPixelRatio(x0), this.$doPixelRatio(y0), this.$doPixelRatio(x1), this.$doPixelRatio(y1));
|
|
219
|
+
}
|
|
220
|
+
createRadialGradient(x0, y0, r0, x1, y1, r1) {
|
|
221
|
+
return this._ctx.createRadialGradient(this.$doPixelRatio(x0), this.$doPixelRatio(y0), this.$doPixelRatio(r0), this.$doPixelRatio(x1), this.$doPixelRatio(y1), this.$doPixelRatio(r1));
|
|
222
|
+
}
|
|
223
|
+
createConicGradient(startAngle, x, y) {
|
|
224
|
+
return this._ctx.createConicGradient(startAngle, this.$doPixelRatio(x), this.$doPixelRatio(y));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Element, ElementSize, ElementSizeController, ViewScaleInfo } from '@idraw/types';
|
|
2
|
+
export declare function calcElementSizeController(elemSize: ElementSize, opts: {
|
|
3
|
+
groupQueue: Element<'group'>[];
|
|
4
|
+
controllerSize?: number;
|
|
5
|
+
viewScaleInfo: ViewScaleInfo;
|
|
6
|
+
}): ElementSizeController;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { createUUID } from './uuid';
|
|
2
|
+
import { getCenterFromTwoPoints } from './point';
|
|
3
|
+
import { calcElementVertexesInGroup, calcElementVertexes } from './vertex';
|
|
4
|
+
function createControllerElementSizeFromCenter(center, opts) {
|
|
5
|
+
const { x, y } = center;
|
|
6
|
+
const { size, angle } = opts;
|
|
7
|
+
return {
|
|
8
|
+
x: x - size / 2,
|
|
9
|
+
y: y - size / 2,
|
|
10
|
+
w: size,
|
|
11
|
+
h: size,
|
|
12
|
+
angle
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function calcElementSizeController(elemSize, opts) {
|
|
16
|
+
const { groupQueue, controllerSize, viewScaleInfo } = opts;
|
|
17
|
+
const ctrlSize = (controllerSize && controllerSize > 0 ? controllerSize : 8) / viewScaleInfo.scale;
|
|
18
|
+
const { x, y, w, h, angle = 0 } = elemSize;
|
|
19
|
+
const ctrlGroupQueue = [
|
|
20
|
+
...[
|
|
21
|
+
{
|
|
22
|
+
uuid: createUUID(),
|
|
23
|
+
x,
|
|
24
|
+
y,
|
|
25
|
+
w,
|
|
26
|
+
h,
|
|
27
|
+
angle,
|
|
28
|
+
type: 'group',
|
|
29
|
+
detail: { children: [] }
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
...groupQueue
|
|
33
|
+
];
|
|
34
|
+
let totalAngle = 0;
|
|
35
|
+
ctrlGroupQueue.forEach(({ angle = 0 }) => {
|
|
36
|
+
totalAngle += angle;
|
|
37
|
+
});
|
|
38
|
+
const vertexes = calcElementVertexesInGroup(elemSize, { groupQueue });
|
|
39
|
+
const topCenter = getCenterFromTwoPoints(vertexes[0], vertexes[1]);
|
|
40
|
+
const rightCenter = getCenterFromTwoPoints(vertexes[1], vertexes[2]);
|
|
41
|
+
const bottomCenter = getCenterFromTwoPoints(vertexes[2], vertexes[3]);
|
|
42
|
+
const leftCenter = getCenterFromTwoPoints(vertexes[3], vertexes[0]);
|
|
43
|
+
const topLeftCenter = vertexes[0];
|
|
44
|
+
const topRightCenter = vertexes[1];
|
|
45
|
+
const bottomRightCenter = vertexes[2];
|
|
46
|
+
const bottomLeftCenter = vertexes[3];
|
|
47
|
+
const topSize = createControllerElementSizeFromCenter(topCenter, { size: ctrlSize, angle: totalAngle });
|
|
48
|
+
const rightSize = createControllerElementSizeFromCenter(rightCenter, { size: ctrlSize, angle: totalAngle });
|
|
49
|
+
const bottomSize = createControllerElementSizeFromCenter(bottomCenter, { size: ctrlSize, angle: totalAngle });
|
|
50
|
+
const leftSize = createControllerElementSizeFromCenter(leftCenter, { size: ctrlSize, angle: totalAngle });
|
|
51
|
+
const topLeftSize = createControllerElementSizeFromCenter(topLeftCenter, { size: ctrlSize, angle: totalAngle });
|
|
52
|
+
const topRightSize = createControllerElementSizeFromCenter(topRightCenter, { size: ctrlSize, angle: totalAngle });
|
|
53
|
+
const bottomLeftSize = createControllerElementSizeFromCenter(bottomLeftCenter, { size: ctrlSize, angle: totalAngle });
|
|
54
|
+
const bottomRightSize = createControllerElementSizeFromCenter(bottomRightCenter, { size: ctrlSize, angle: totalAngle });
|
|
55
|
+
const sizeController = {
|
|
56
|
+
elementWrapper: vertexes,
|
|
57
|
+
left: {
|
|
58
|
+
type: 'left',
|
|
59
|
+
vertexes: calcElementVertexes(leftSize),
|
|
60
|
+
center: leftCenter
|
|
61
|
+
},
|
|
62
|
+
right: {
|
|
63
|
+
type: 'right',
|
|
64
|
+
vertexes: calcElementVertexes(rightSize),
|
|
65
|
+
center: rightCenter
|
|
66
|
+
},
|
|
67
|
+
top: {
|
|
68
|
+
type: 'top',
|
|
69
|
+
vertexes: calcElementVertexes(topSize),
|
|
70
|
+
center: topCenter
|
|
71
|
+
},
|
|
72
|
+
bottom: {
|
|
73
|
+
type: 'bottom',
|
|
74
|
+
vertexes: calcElementVertexes(bottomSize),
|
|
75
|
+
center: bottomCenter
|
|
76
|
+
},
|
|
77
|
+
topLeft: {
|
|
78
|
+
type: 'top-left',
|
|
79
|
+
vertexes: calcElementVertexes(topLeftSize),
|
|
80
|
+
center: topLeftCenter
|
|
81
|
+
},
|
|
82
|
+
topRight: {
|
|
83
|
+
type: 'top-right',
|
|
84
|
+
vertexes: calcElementVertexes(topRightSize),
|
|
85
|
+
center: topRightCenter
|
|
86
|
+
},
|
|
87
|
+
bottomLeft: {
|
|
88
|
+
type: 'bottom-left',
|
|
89
|
+
vertexes: calcElementVertexes(bottomLeftSize),
|
|
90
|
+
center: bottomLeftCenter
|
|
91
|
+
},
|
|
92
|
+
bottomRight: {
|
|
93
|
+
type: 'bottom-right',
|
|
94
|
+
vertexes: calcElementVertexes(bottomRightSize),
|
|
95
|
+
center: bottomRightCenter
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
return sizeController;
|
|
99
|
+
}
|
package/dist/esm/lib/data.d.ts
CHANGED
package/dist/esm/lib/data.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createAssetId } from './uuid';
|
|
1
2
|
export function deepClone(target) {
|
|
2
3
|
function _clone(t) {
|
|
3
4
|
const type = is(t);
|
|
@@ -17,11 +18,75 @@ export function deepClone(target) {
|
|
|
17
18
|
keys.forEach((key) => {
|
|
18
19
|
obj[key] = _clone(t[key]);
|
|
19
20
|
});
|
|
21
|
+
const symbolKeys = Object.getOwnPropertySymbols(t);
|
|
22
|
+
symbolKeys.forEach((key) => {
|
|
23
|
+
obj[key] = _clone(t[key]);
|
|
24
|
+
});
|
|
20
25
|
return obj;
|
|
21
26
|
}
|
|
22
27
|
}
|
|
23
28
|
return _clone(target);
|
|
24
29
|
}
|
|
25
|
-
function is(
|
|
26
|
-
return Object.prototype.toString
|
|
30
|
+
function is(target) {
|
|
31
|
+
return Object.prototype.toString
|
|
32
|
+
.call(target)
|
|
33
|
+
.replace(/[\]|\[]{1,1}/gi, '')
|
|
34
|
+
.split(' ')[1];
|
|
35
|
+
}
|
|
36
|
+
export function sortDataAsserts(data, opts) {
|
|
37
|
+
const assets = data.assets || {};
|
|
38
|
+
let sortedData = data;
|
|
39
|
+
if ((opts === null || opts === void 0 ? void 0 : opts.clone) === true) {
|
|
40
|
+
sortedData = deepClone(data);
|
|
41
|
+
}
|
|
42
|
+
const _scanElements = (elems) => {
|
|
43
|
+
elems.forEach((elem) => {
|
|
44
|
+
if (elem.type === 'image' && elem.detail.src) {
|
|
45
|
+
const src = elem.detail.src;
|
|
46
|
+
const assetUUID = createAssetId(src);
|
|
47
|
+
if (!assets[assetUUID]) {
|
|
48
|
+
assets[assetUUID] = {
|
|
49
|
+
type: 'image',
|
|
50
|
+
value: src
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
elem.detail.src = assetUUID;
|
|
54
|
+
}
|
|
55
|
+
else if (elem.type === 'svg') {
|
|
56
|
+
const svg = elem.detail.svg;
|
|
57
|
+
const assetUUID = createAssetId(svg);
|
|
58
|
+
if (!assets[assetUUID]) {
|
|
59
|
+
assets[assetUUID] = {
|
|
60
|
+
type: 'svg',
|
|
61
|
+
value: svg
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
elem.detail.svg = assetUUID;
|
|
65
|
+
}
|
|
66
|
+
else if (elem.type === 'html') {
|
|
67
|
+
const html = elem.detail.html;
|
|
68
|
+
const assetUUID = createAssetId(html);
|
|
69
|
+
if (!assets[assetUUID]) {
|
|
70
|
+
assets[assetUUID] = {
|
|
71
|
+
type: 'svg',
|
|
72
|
+
value: html
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
elem.detail.html = assetUUID;
|
|
76
|
+
}
|
|
77
|
+
else if (elem.type === 'group' && Array.isArray(elem.detail.children)) {
|
|
78
|
+
const groupAssets = elem.detail.assets || {};
|
|
79
|
+
Object.keys(groupAssets).forEach((assetId) => {
|
|
80
|
+
if (!assets[assetId]) {
|
|
81
|
+
assets[assetId] = groupAssets[assetId];
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
delete elem.detail.assets;
|
|
85
|
+
_scanElements(elem.detail.children);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
_scanElements(sortedData.elements);
|
|
90
|
+
sortedData.assets = assets;
|
|
91
|
+
return sortedData;
|
|
27
92
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Data, Element, Elements, ElementType, ViewContextSize, ViewSizeInfo, RecursivePartial } from '@idraw/types';
|
|
2
|
+
export declare function getSelectedElementUUIDs(data: Data, indexes: Array<number | string>): string[];
|
|
3
|
+
export declare function validateElements(elements: Array<Element<ElementType>>): boolean;
|
|
4
|
+
export declare function calcElementsContextSize(elements: Array<Element<ElementType>>, opts?: {
|
|
5
|
+
viewWidth: number;
|
|
6
|
+
viewHeight: number;
|
|
7
|
+
extend?: boolean;
|
|
8
|
+
}): ViewContextSize;
|
|
9
|
+
export declare function calcElementsViewInfo(elements: Array<Element<ElementType>>, prevViewSize: ViewSizeInfo, options?: {
|
|
10
|
+
extend: boolean;
|
|
11
|
+
}): {
|
|
12
|
+
contextSize: ViewContextSize;
|
|
13
|
+
};
|
|
14
|
+
export declare function getElemenetsAssetIds(elements: Elements): string[];
|
|
15
|
+
export declare function findElementFromList(uuid: string, list: Element<ElementType>[]): Element<ElementType> | null;
|
|
16
|
+
export declare function findElementsFromList(uuids: string[], list: Element<ElementType>[]): Element<ElementType>[];
|
|
17
|
+
export declare function getGroupQueueFromList(uuid: string, elements: Element<ElementType>[]): Element<'group'>[];
|
|
18
|
+
export declare function updateElementInList(uuid: string, updateContent: RecursivePartial<Element<ElementType>>, elements: Element<ElementType>[]): Element<ElementType>[];
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { rotateElementVertexes } from './rotate';
|
|
2
|
+
import { isAssetId } from './uuid';
|
|
3
|
+
function getGroupUUIDs(elements, index) {
|
|
4
|
+
var _a;
|
|
5
|
+
const uuids = [];
|
|
6
|
+
if (typeof index === 'string' && /^\d+(\.\d+)*$/.test(index)) {
|
|
7
|
+
const nums = index.split('.');
|
|
8
|
+
let target = elements;
|
|
9
|
+
while (nums.length > 0) {
|
|
10
|
+
const num = nums.shift();
|
|
11
|
+
if (typeof num === 'string') {
|
|
12
|
+
const elem = target[parseInt(num)];
|
|
13
|
+
if (elem && nums.length === 0) {
|
|
14
|
+
uuids.push(elem.uuid);
|
|
15
|
+
}
|
|
16
|
+
else if (elem.type === 'group' && nums.length > 0) {
|
|
17
|
+
target = ((_a = elem === null || elem === void 0 ? void 0 : elem.detail) === null || _a === void 0 ? void 0 : _a.children) || [];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return uuids;
|
|
24
|
+
}
|
|
25
|
+
export function getSelectedElementUUIDs(data, indexes) {
|
|
26
|
+
var _a;
|
|
27
|
+
let uuids = [];
|
|
28
|
+
if (Array.isArray(data === null || data === void 0 ? void 0 : data.elements) && ((_a = data === null || data === void 0 ? void 0 : data.elements) === null || _a === void 0 ? void 0 : _a.length) > 0 && Array.isArray(indexes) && indexes.length > 0) {
|
|
29
|
+
indexes.forEach((idx) => {
|
|
30
|
+
var _a;
|
|
31
|
+
if (typeof idx === 'number') {
|
|
32
|
+
if ((_a = data === null || data === void 0 ? void 0 : data.elements) === null || _a === void 0 ? void 0 : _a[idx]) {
|
|
33
|
+
uuids.push(data.elements[idx].uuid);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else if (typeof idx === 'string') {
|
|
37
|
+
uuids = uuids.concat(getGroupUUIDs(data.elements, idx));
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return uuids;
|
|
42
|
+
}
|
|
43
|
+
export function validateElements(elements) {
|
|
44
|
+
let isValid = true;
|
|
45
|
+
if (Array.isArray(elements)) {
|
|
46
|
+
const uuids = [];
|
|
47
|
+
elements.forEach((elem) => {
|
|
48
|
+
var _a;
|
|
49
|
+
if (typeof elem.uuid === 'string' && elem.uuid) {
|
|
50
|
+
if (uuids.includes(elem.uuid)) {
|
|
51
|
+
isValid = false;
|
|
52
|
+
console.warn(`Duplicate uuids: ${elem.uuid}`);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
uuids.push(elem.uuid);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
isValid = false;
|
|
60
|
+
console.warn('Element missing uuid', elem);
|
|
61
|
+
}
|
|
62
|
+
if (elem.type === 'group') {
|
|
63
|
+
isValid = validateElements((_a = elem === null || elem === void 0 ? void 0 : elem.detail) === null || _a === void 0 ? void 0 : _a.children);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return isValid;
|
|
68
|
+
}
|
|
69
|
+
export function calcElementsContextSize(elements, opts) {
|
|
70
|
+
const area = { x: 0, y: 0, w: 0, h: 0 };
|
|
71
|
+
elements.forEach((elem) => {
|
|
72
|
+
const elemSize = {
|
|
73
|
+
x: elem.x,
|
|
74
|
+
y: elem.y,
|
|
75
|
+
w: elem.w,
|
|
76
|
+
h: elem.h,
|
|
77
|
+
angle: elem.angle
|
|
78
|
+
};
|
|
79
|
+
if (elemSize.angle && (elemSize.angle > 0 || elemSize.angle < 0)) {
|
|
80
|
+
const ves = rotateElementVertexes(elemSize);
|
|
81
|
+
if (ves.length === 4) {
|
|
82
|
+
const xList = [ves[0].x, ves[1].x, ves[2].x, ves[3].x];
|
|
83
|
+
const yList = [ves[0].y, ves[1].y, ves[2].y, ves[3].y];
|
|
84
|
+
elemSize.x = Math.min(...xList);
|
|
85
|
+
elemSize.y = Math.min(...yList);
|
|
86
|
+
elemSize.w = Math.abs(Math.max(...xList) - Math.min(...xList));
|
|
87
|
+
elemSize.h = Math.abs(Math.max(...yList) - Math.min(...yList));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const areaStartX = Math.min(elemSize.x, area.x);
|
|
91
|
+
const areaStartY = Math.min(elemSize.y, area.y);
|
|
92
|
+
const areaEndX = Math.max(elemSize.x + elemSize.w, area.x + area.w);
|
|
93
|
+
const areaEndY = Math.max(elemSize.y + elemSize.h, area.y + area.h);
|
|
94
|
+
area.x = areaStartX;
|
|
95
|
+
area.y = areaStartY;
|
|
96
|
+
area.w = Math.abs(areaEndX - areaStartX);
|
|
97
|
+
area.h = Math.abs(areaEndY - areaStartY);
|
|
98
|
+
});
|
|
99
|
+
if (opts === null || opts === void 0 ? void 0 : opts.extend) {
|
|
100
|
+
area.x = Math.min(area.x, 0);
|
|
101
|
+
area.y = Math.min(area.y, 0);
|
|
102
|
+
}
|
|
103
|
+
const ctxSize = {
|
|
104
|
+
contextWidth: area.w,
|
|
105
|
+
contextHeight: area.h
|
|
106
|
+
};
|
|
107
|
+
if ((opts === null || opts === void 0 ? void 0 : opts.viewWidth) && (opts === null || opts === void 0 ? void 0 : opts.viewHeight) && (opts === null || opts === void 0 ? void 0 : opts.viewWidth) > 0 && (opts === null || opts === void 0 ? void 0 : opts.viewHeight) > 0) {
|
|
108
|
+
if (opts.viewWidth > area.x + area.w) {
|
|
109
|
+
ctxSize.contextWidth = opts.viewWidth - area.x;
|
|
110
|
+
}
|
|
111
|
+
if (opts.viewHeight > area.y + area.h) {
|
|
112
|
+
ctxSize.contextHeight = opts.viewHeight - area.y;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return ctxSize;
|
|
116
|
+
}
|
|
117
|
+
export function calcElementsViewInfo(elements, prevViewSize, options) {
|
|
118
|
+
const contextSize = calcElementsContextSize(elements, { viewWidth: prevViewSize.width, viewHeight: prevViewSize.height, extend: options === null || options === void 0 ? void 0 : options.extend });
|
|
119
|
+
if ((options === null || options === void 0 ? void 0 : options.extend) === true) {
|
|
120
|
+
contextSize.contextWidth = Math.max(contextSize.contextWidth, prevViewSize.contextWidth);
|
|
121
|
+
contextSize.contextHeight = Math.max(contextSize.contextHeight, prevViewSize.contextHeight);
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
contextSize
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
export function getElemenetsAssetIds(elements) {
|
|
128
|
+
const assetIds = [];
|
|
129
|
+
const _scanElements = (elems) => {
|
|
130
|
+
elems.forEach((elem) => {
|
|
131
|
+
if (elem.type === 'image' && isAssetId(elem.detail.src)) {
|
|
132
|
+
assetIds.push(elem.detail.src);
|
|
133
|
+
}
|
|
134
|
+
else if (elem.type === 'svg' && isAssetId(elem.detail.svg)) {
|
|
135
|
+
assetIds.push(elem.detail.svg);
|
|
136
|
+
}
|
|
137
|
+
else if (elem.type === 'html' && elem.detail.html) {
|
|
138
|
+
assetIds.push(elem.detail.html);
|
|
139
|
+
}
|
|
140
|
+
else if (elem.type === 'group' && Array.isArray(elem.detail.children)) {
|
|
141
|
+
_scanElements(elem.detail.children);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
};
|
|
145
|
+
_scanElements(elements);
|
|
146
|
+
return assetIds;
|
|
147
|
+
}
|
|
148
|
+
export function findElementFromList(uuid, list) {
|
|
149
|
+
var _a;
|
|
150
|
+
let result = null;
|
|
151
|
+
for (let i = 0; i < list.length; i++) {
|
|
152
|
+
const elem = list[i];
|
|
153
|
+
if (elem.uuid === uuid) {
|
|
154
|
+
result = elem;
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
else if (!result && elem.type === 'group') {
|
|
158
|
+
const resultInGroup = findElementFromList(uuid, ((_a = elem === null || elem === void 0 ? void 0 : elem.detail) === null || _a === void 0 ? void 0 : _a.children) || []);
|
|
159
|
+
if ((resultInGroup === null || resultInGroup === void 0 ? void 0 : resultInGroup.uuid) === uuid) {
|
|
160
|
+
result = resultInGroup;
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return result;
|
|
166
|
+
}
|
|
167
|
+
export function findElementsFromList(uuids, list) {
|
|
168
|
+
const result = [];
|
|
169
|
+
function _find(elements) {
|
|
170
|
+
var _a;
|
|
171
|
+
for (let i = 0; i < elements.length; i++) {
|
|
172
|
+
const elem = elements[i];
|
|
173
|
+
if (uuids.includes(elem.uuid)) {
|
|
174
|
+
result.push(elem);
|
|
175
|
+
}
|
|
176
|
+
else if (elem.type === 'group') {
|
|
177
|
+
_find(((_a = elem === null || elem === void 0 ? void 0 : elem.detail) === null || _a === void 0 ? void 0 : _a.children) || []);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
_find(list);
|
|
182
|
+
return result;
|
|
183
|
+
}
|
|
184
|
+
export function getGroupQueueFromList(uuid, elements) {
|
|
185
|
+
const groupQueue = [];
|
|
186
|
+
function _scan(uuid, elements) {
|
|
187
|
+
var _a;
|
|
188
|
+
let result = null;
|
|
189
|
+
for (let i = 0; i < elements.length; i++) {
|
|
190
|
+
const elem = elements[i];
|
|
191
|
+
if (elem.uuid === uuid) {
|
|
192
|
+
result = elem;
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
else if (!result && elem.type === 'group') {
|
|
196
|
+
groupQueue.push(elem);
|
|
197
|
+
const resultInGroup = _scan(uuid, ((_a = elem === null || elem === void 0 ? void 0 : elem.detail) === null || _a === void 0 ? void 0 : _a.children) || []);
|
|
198
|
+
if ((resultInGroup === null || resultInGroup === void 0 ? void 0 : resultInGroup.uuid) === uuid) {
|
|
199
|
+
result = resultInGroup;
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
groupQueue.pop();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
_scan(uuid, elements);
|
|
208
|
+
return groupQueue;
|
|
209
|
+
}
|
|
210
|
+
function mergeElement(originElem, updateContent) {
|
|
211
|
+
const commonKeys = Object.keys(updateContent);
|
|
212
|
+
for (let i = 0; i < commonKeys.length; i++) {
|
|
213
|
+
const commonKey = commonKeys[i];
|
|
214
|
+
if (['x', 'y', 'w', 'h', 'angle', 'name'].includes(commonKey)) {
|
|
215
|
+
originElem[commonKey] = updateContent[commonKey];
|
|
216
|
+
}
|
|
217
|
+
else if (['detail', 'operations'].includes(commonKey)) {
|
|
218
|
+
if (istype.json(updateContent[commonKey]) && istype.json(originElem[commonKey])) {
|
|
219
|
+
originElem[commonKey] = Object.assign(Object.assign({}, originElem[commonKey]), updateContent[commonKey]);
|
|
220
|
+
}
|
|
221
|
+
else if (istype.array(updateContent[commonKey]) && istype.array(originElem[commonKey])) {
|
|
222
|
+
originElem[commonKey] = Object.assign(Object.assign({}, originElem[commonKey]), updateContent[commonKey]);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return originElem;
|
|
227
|
+
}
|
|
228
|
+
export function updateElementInList(uuid, updateContent, elements) {
|
|
229
|
+
var _a;
|
|
230
|
+
for (let i = 0; i < elements.length; i++) {
|
|
231
|
+
const elem = elements[i];
|
|
232
|
+
if (elem.uuid === uuid) {
|
|
233
|
+
mergeElement(elem, updateContent);
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
else if (elem.type === 'group') {
|
|
237
|
+
updateElementInList(uuid, updateContent, ((_a = elem === null || elem === void 0 ? void 0 : elem.detail) === null || _a === void 0 ? void 0 : _a.children) || []);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return elements;
|
|
241
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { UtilEventEmitter } from '@idraw/types';
|
|
2
|
+
export declare class EventEmitter<T extends Record<string, any>> implements UtilEventEmitter<T> {
|
|
3
|
+
private _listeners;
|
|
4
|
+
constructor();
|
|
5
|
+
on<K extends keyof T>(eventKey: K, callback: (e: T[K]) => void): void;
|
|
6
|
+
off<K extends keyof T>(eventKey: K, callback: (e: T[K]) => void): void;
|
|
7
|
+
trigger<K extends keyof T>(eventKey: K, e: T[K]): boolean;
|
|
8
|
+
has<K extends keyof T>(name: K | string): boolean;
|
|
9
|
+
}
|