@idraw/renderer 0.3.1 → 0.4.0-alpha.3
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/README.md +1 -1
- package/dist/esm/draw/base.d.ts +14 -0
- package/dist/esm/draw/base.js +245 -0
- package/dist/esm/draw/circle.d.ts +2 -0
- package/dist/esm/draw/circle.js +28 -0
- package/dist/esm/draw/elements.d.ts +2 -0
- package/dist/esm/draw/elements.js +16 -0
- package/dist/esm/draw/group.d.ts +3 -0
- package/dist/esm/draw/group.js +110 -0
- package/dist/esm/draw/html.d.ts +2 -0
- package/dist/esm/draw/html.js +14 -0
- package/dist/esm/draw/image.d.ts +2 -0
- package/dist/esm/draw/image.js +14 -0
- package/dist/esm/draw/index.d.ts +7 -0
- package/dist/esm/draw/index.js +7 -0
- package/dist/esm/draw/path.d.ts +2 -0
- package/dist/esm/draw/path.js +49 -0
- package/dist/esm/draw/rect.d.ts +2 -0
- package/dist/esm/draw/rect.js +23 -0
- package/dist/esm/draw/svg.d.ts +2 -0
- package/dist/esm/draw/svg.js +14 -0
- package/dist/esm/draw/text.d.ts +2 -0
- package/dist/esm/draw/text.js +113 -0
- package/dist/esm/index.d.ts +9 -24
- package/dist/esm/index.js +46 -124
- package/dist/esm/loader.d.ts +17 -0
- package/dist/esm/loader.js +151 -0
- package/dist/index.global.js +767 -856
- package/dist/index.global.min.js +1 -1
- package/package.json +6 -6
- package/LICENSE +0 -21
- package/dist/esm/constant/element.d.ts +0 -2
- package/dist/esm/constant/element.js +0 -10
- package/dist/esm/constant/static.d.ts +0 -11
- package/dist/esm/constant/static.js +0 -13
- package/dist/esm/lib/calculate.d.ts +0 -5
- package/dist/esm/lib/calculate.js +0 -64
- package/dist/esm/lib/diff.d.ts +0 -6
- package/dist/esm/lib/diff.js +0 -82
- package/dist/esm/lib/draw/base.d.ts +0 -5
- package/dist/esm/lib/draw/base.js +0 -89
- package/dist/esm/lib/draw/circle.d.ts +0 -2
- package/dist/esm/lib/draw/circle.js +0 -28
- package/dist/esm/lib/draw/html.d.ts +0 -3
- package/dist/esm/lib/draw/html.js +0 -9
- package/dist/esm/lib/draw/image.d.ts +0 -3
- package/dist/esm/lib/draw/image.js +0 -9
- package/dist/esm/lib/draw/index.d.ts +0 -3
- package/dist/esm/lib/draw/index.js +0 -55
- package/dist/esm/lib/draw/rect.d.ts +0 -2
- package/dist/esm/lib/draw/rect.js +0 -4
- package/dist/esm/lib/draw/svg.d.ts +0 -3
- package/dist/esm/lib/draw/svg.js +0 -9
- package/dist/esm/lib/draw/text.d.ts +0 -3
- package/dist/esm/lib/draw/text.js +0 -128
- package/dist/esm/lib/index.d.ts +0 -6
- package/dist/esm/lib/index.js +0 -6
- package/dist/esm/lib/loader-event.d.ts +0 -33
- package/dist/esm/lib/loader-event.js +0 -50
- package/dist/esm/lib/loader.d.ts +0 -25
- package/dist/esm/lib/loader.js +0 -246
- package/dist/esm/lib/parse.d.ts +0 -2
- package/dist/esm/lib/parse.js +0 -32
- package/dist/esm/lib/renderer-event.d.ts +0 -32
- package/dist/esm/lib/renderer-event.js +0 -50
- package/dist/esm/lib/temp.d.ts +0 -22
- package/dist/esm/lib/temp.js +0 -29
- package/dist/esm/lib/transform.d.ts +0 -4
- package/dist/esm/lib/transform.js +0 -20
- package/dist/esm/lib/value.d.ts +0 -2
- package/dist/esm/lib/value.js +0 -7
- package/dist/esm/util/filter.d.ts +0 -1
- package/dist/esm/util/filter.js +0 -3
package/README.md
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ViewContext2D, Element, ElementType, ElementSize, ViewScaleInfo, ViewSizeInfo } from '@idraw/types';
|
|
2
|
+
export declare function drawBox(ctx: ViewContext2D, viewElem: Element<ElementType>, opts: {
|
|
3
|
+
originElem: Element<ElementType>;
|
|
4
|
+
calcElemSize: ElementSize;
|
|
5
|
+
pattern?: string | CanvasPattern | null;
|
|
6
|
+
renderContent: Function;
|
|
7
|
+
viewScaleInfo: ViewScaleInfo;
|
|
8
|
+
viewSizeInfo: ViewSizeInfo;
|
|
9
|
+
}): void;
|
|
10
|
+
export declare function drawBoxShadow(ctx: ViewContext2D, viewElem: Element<ElementType>, opts: {
|
|
11
|
+
viewScaleInfo: ViewScaleInfo;
|
|
12
|
+
viewSizeInfo: ViewSizeInfo;
|
|
13
|
+
renderContent: Function;
|
|
14
|
+
}): void;
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { istype, isColorStr, generateSVGPath, rotateElement, is } from '@idraw/util';
|
|
2
|
+
export function drawBox(ctx, viewElem, opts) {
|
|
3
|
+
var _a, _b;
|
|
4
|
+
if (((_a = viewElem === null || viewElem === void 0 ? void 0 : viewElem.detail) === null || _a === void 0 ? void 0 : _a.opacity) !== undefined && ((_b = viewElem === null || viewElem === void 0 ? void 0 : viewElem.detail) === null || _b === void 0 ? void 0 : _b.opacity) > 0) {
|
|
5
|
+
ctx.globalAlpha = viewElem.detail.opacity;
|
|
6
|
+
}
|
|
7
|
+
else {
|
|
8
|
+
ctx.globalAlpha = 1;
|
|
9
|
+
}
|
|
10
|
+
const { pattern, renderContent, originElem, calcElemSize, viewScaleInfo, viewSizeInfo } = opts || {};
|
|
11
|
+
drawClipPath(ctx, viewElem, {
|
|
12
|
+
originElem,
|
|
13
|
+
calcElemSize,
|
|
14
|
+
viewScaleInfo,
|
|
15
|
+
viewSizeInfo,
|
|
16
|
+
renderContent: () => {
|
|
17
|
+
drawBoxBorder(ctx, viewElem, { viewScaleInfo, viewSizeInfo });
|
|
18
|
+
drawBoxBackground(ctx, viewElem, { pattern, viewScaleInfo, viewSizeInfo });
|
|
19
|
+
renderContent === null || renderContent === void 0 ? void 0 : renderContent();
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
ctx.globalAlpha = 1;
|
|
23
|
+
}
|
|
24
|
+
function drawClipPath(ctx, viewElem, opts) {
|
|
25
|
+
const { renderContent, originElem, calcElemSize, viewScaleInfo, viewSizeInfo } = opts;
|
|
26
|
+
const totalScale = viewScaleInfo.scale * viewSizeInfo.devicePixelRatio;
|
|
27
|
+
const { clipPath } = (originElem === null || originElem === void 0 ? void 0 : originElem.detail) || {};
|
|
28
|
+
if (clipPath && calcElemSize && clipPath.commands) {
|
|
29
|
+
const { x, y, w, h } = calcElemSize;
|
|
30
|
+
const { originW, originH, originX, originY } = clipPath;
|
|
31
|
+
const scaleW = w / originW;
|
|
32
|
+
const scaleH = h / originH;
|
|
33
|
+
const viewOriginX = originX * scaleW;
|
|
34
|
+
const viewOriginY = originY * scaleH;
|
|
35
|
+
let internalX = x - viewOriginX;
|
|
36
|
+
let internalY = y - viewOriginY;
|
|
37
|
+
ctx.save();
|
|
38
|
+
ctx.translate(internalX, internalY);
|
|
39
|
+
ctx.scale(totalScale * scaleW, totalScale * scaleH);
|
|
40
|
+
const pathStr = generateSVGPath(clipPath.commands || []);
|
|
41
|
+
const path2d = new Path2D(pathStr);
|
|
42
|
+
ctx.clip(path2d);
|
|
43
|
+
ctx.translate(0 - internalX, 0 - internalY);
|
|
44
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
45
|
+
rotateElement(ctx, Object.assign({}, viewElem), () => {
|
|
46
|
+
renderContent === null || renderContent === void 0 ? void 0 : renderContent();
|
|
47
|
+
});
|
|
48
|
+
ctx.restore();
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
renderContent === null || renderContent === void 0 ? void 0 : renderContent();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function drawBoxBackground(ctx, viewElem, opts) {
|
|
55
|
+
var _a, _b;
|
|
56
|
+
const { pattern, viewScaleInfo } = opts;
|
|
57
|
+
let transform = [];
|
|
58
|
+
if (viewElem.detail.background || pattern) {
|
|
59
|
+
const { x, y, w, h } = viewElem;
|
|
60
|
+
let r = (viewElem.detail.borderRadius || 0) * viewScaleInfo.scale;
|
|
61
|
+
r = Math.min(r, w / 2, h / 2);
|
|
62
|
+
if (w < r * 2 || h < r * 2) {
|
|
63
|
+
r = 0;
|
|
64
|
+
}
|
|
65
|
+
ctx.beginPath();
|
|
66
|
+
ctx.moveTo(x + r, y);
|
|
67
|
+
ctx.arcTo(x + w, y, x + w, y + h, r);
|
|
68
|
+
ctx.arcTo(x + w, y + h, x, y + h, r);
|
|
69
|
+
ctx.arcTo(x, y + h, x, y, r);
|
|
70
|
+
ctx.arcTo(x, y, x + w, y, r);
|
|
71
|
+
ctx.closePath();
|
|
72
|
+
if (typeof pattern === 'string') {
|
|
73
|
+
ctx.fillStyle = pattern;
|
|
74
|
+
}
|
|
75
|
+
else if (['CanvasPattern'].includes(istype.type(pattern))) {
|
|
76
|
+
ctx.fillStyle = pattern;
|
|
77
|
+
}
|
|
78
|
+
else if (typeof viewElem.detail.background === 'string') {
|
|
79
|
+
ctx.fillStyle = viewElem.detail.background;
|
|
80
|
+
}
|
|
81
|
+
else if (((_a = viewElem.detail.background) === null || _a === void 0 ? void 0 : _a.type) === 'linearGradient') {
|
|
82
|
+
const { start, end, stops } = viewElem.detail.background;
|
|
83
|
+
const viewStart = {
|
|
84
|
+
x: start.x + x,
|
|
85
|
+
y: start.y + y
|
|
86
|
+
};
|
|
87
|
+
const viewEnd = {
|
|
88
|
+
x: end.x + x,
|
|
89
|
+
y: end.y + y
|
|
90
|
+
};
|
|
91
|
+
const linearGradient = ctx.createLinearGradient(viewStart.x, viewStart.y, viewEnd.x, viewEnd.y);
|
|
92
|
+
stops.forEach((stop) => {
|
|
93
|
+
linearGradient.addColorStop(stop.offset, stop.color);
|
|
94
|
+
});
|
|
95
|
+
ctx.fillStyle = linearGradient;
|
|
96
|
+
}
|
|
97
|
+
else if (((_b = viewElem.detail.background) === null || _b === void 0 ? void 0 : _b.type) === 'radialGradient') {
|
|
98
|
+
const { inner, outer, stops } = viewElem.detail.background;
|
|
99
|
+
transform = viewElem.detail.background.transform || [];
|
|
100
|
+
const viewInner = {
|
|
101
|
+
x: inner.x,
|
|
102
|
+
y: inner.y,
|
|
103
|
+
radius: inner.radius * viewScaleInfo.scale
|
|
104
|
+
};
|
|
105
|
+
const viewOuter = {
|
|
106
|
+
x: outer.x,
|
|
107
|
+
y: outer.y,
|
|
108
|
+
radius: outer.radius * viewScaleInfo.scale
|
|
109
|
+
};
|
|
110
|
+
const radialGradient = ctx.createRadialGradient(viewInner.x, viewInner.y, viewInner.radius, viewOuter.x, viewOuter.y, viewOuter.radius);
|
|
111
|
+
stops.forEach((stop) => {
|
|
112
|
+
radialGradient.addColorStop(stop.offset, stop.color);
|
|
113
|
+
});
|
|
114
|
+
ctx.fillStyle = radialGradient;
|
|
115
|
+
if (transform && transform.length > 0) {
|
|
116
|
+
for (let i = 0; i < (transform === null || transform === void 0 ? void 0 : transform.length); i++) {
|
|
117
|
+
const action = transform[i];
|
|
118
|
+
if (action.method === 'translate') {
|
|
119
|
+
ctx.translate(action.args[0] + x, action.args[1] + y);
|
|
120
|
+
}
|
|
121
|
+
else if (action.method === 'rotate') {
|
|
122
|
+
ctx.rotate(...action.args);
|
|
123
|
+
}
|
|
124
|
+
else if (action.method === 'scale') {
|
|
125
|
+
ctx.scale(...action.args);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
ctx.fill();
|
|
131
|
+
if (transform && transform.length > 0) {
|
|
132
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function drawBoxBorder(ctx, viewElem, opts) {
|
|
137
|
+
if (!isColorStr(viewElem.detail.borderColor)) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const { viewScaleInfo } = opts;
|
|
141
|
+
let borderColor = '#000000';
|
|
142
|
+
if (isColorStr(viewElem.detail.borderColor) === true) {
|
|
143
|
+
borderColor = viewElem.detail.borderColor;
|
|
144
|
+
}
|
|
145
|
+
const { borderWidth, borderRadius, borderDash } = viewElem.detail;
|
|
146
|
+
let bw = 0;
|
|
147
|
+
if (typeof borderWidth === 'number') {
|
|
148
|
+
bw = borderWidth || 1;
|
|
149
|
+
}
|
|
150
|
+
bw = bw * viewScaleInfo.scale;
|
|
151
|
+
let r = borderRadius || 0;
|
|
152
|
+
ctx.strokeStyle = borderColor;
|
|
153
|
+
ctx.setLineDash(borderDash || []);
|
|
154
|
+
let borderTop = 0;
|
|
155
|
+
let borderRight = 0;
|
|
156
|
+
let borderBottom = 0;
|
|
157
|
+
let borderLeft = 0;
|
|
158
|
+
if (Array.isArray(borderWidth)) {
|
|
159
|
+
borderTop = borderWidth[0] || 0;
|
|
160
|
+
borderRight = borderWidth[1] || 0;
|
|
161
|
+
borderBottom = borderWidth[2] || 0;
|
|
162
|
+
borderLeft = borderWidth[3] || 0;
|
|
163
|
+
}
|
|
164
|
+
if (borderLeft || borderRight || borderTop || borderBottom) {
|
|
165
|
+
const { x, y, w, h } = viewElem;
|
|
166
|
+
if (borderLeft) {
|
|
167
|
+
ctx.beginPath();
|
|
168
|
+
ctx.lineWidth = borderLeft * viewScaleInfo.scale;
|
|
169
|
+
ctx.moveTo(x, y);
|
|
170
|
+
ctx.lineTo(x, y + h);
|
|
171
|
+
ctx.closePath();
|
|
172
|
+
ctx.stroke();
|
|
173
|
+
}
|
|
174
|
+
if (borderRight) {
|
|
175
|
+
ctx.beginPath();
|
|
176
|
+
ctx.lineWidth = borderRight * viewScaleInfo.scale;
|
|
177
|
+
ctx.moveTo(x + w, y);
|
|
178
|
+
ctx.lineTo(x + w, y + h);
|
|
179
|
+
ctx.closePath();
|
|
180
|
+
ctx.stroke();
|
|
181
|
+
}
|
|
182
|
+
if (borderTop) {
|
|
183
|
+
ctx.beginPath();
|
|
184
|
+
ctx.lineWidth = borderTop * viewScaleInfo.scale;
|
|
185
|
+
ctx.moveTo(x, y);
|
|
186
|
+
ctx.lineTo(x + w, y);
|
|
187
|
+
ctx.closePath();
|
|
188
|
+
ctx.stroke();
|
|
189
|
+
}
|
|
190
|
+
if (borderBottom) {
|
|
191
|
+
ctx.beginPath();
|
|
192
|
+
ctx.lineWidth = borderBottom * viewScaleInfo.scale;
|
|
193
|
+
ctx.moveTo(x, y + h);
|
|
194
|
+
ctx.lineTo(x + w, y + h);
|
|
195
|
+
ctx.closePath();
|
|
196
|
+
ctx.stroke();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
let { x, y, w, h } = viewElem;
|
|
201
|
+
const { boxSizing } = viewElem.detail;
|
|
202
|
+
if (boxSizing === 'border-box') {
|
|
203
|
+
x = viewElem.x;
|
|
204
|
+
y = viewElem.y;
|
|
205
|
+
w = viewElem.w;
|
|
206
|
+
h = viewElem.h;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
x = viewElem.x - bw;
|
|
210
|
+
y = viewElem.y - bw;
|
|
211
|
+
w = viewElem.w + bw * 2;
|
|
212
|
+
h = viewElem.h + bw * 2;
|
|
213
|
+
}
|
|
214
|
+
r = Math.min(r, w / 2, h / 2);
|
|
215
|
+
if (r < w / 2 && r < h / 2) {
|
|
216
|
+
r = r + bw / 2;
|
|
217
|
+
}
|
|
218
|
+
ctx.beginPath();
|
|
219
|
+
ctx.lineWidth = bw;
|
|
220
|
+
ctx.moveTo(x + r, y);
|
|
221
|
+
ctx.arcTo(x + w, y, x + w, y + h, r);
|
|
222
|
+
ctx.arcTo(x + w, y + h, x, y + h, r);
|
|
223
|
+
ctx.arcTo(x, y + h, x, y, r);
|
|
224
|
+
ctx.arcTo(x, y, x + w, y, r);
|
|
225
|
+
ctx.closePath();
|
|
226
|
+
ctx.stroke();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
export function drawBoxShadow(ctx, viewElem, opts) {
|
|
230
|
+
const { detail } = viewElem;
|
|
231
|
+
const { viewScaleInfo, renderContent } = opts;
|
|
232
|
+
const { shadowColor, shadowOffsetX, shadowOffsetY, shadowBlur } = detail;
|
|
233
|
+
if (is.number(shadowBlur)) {
|
|
234
|
+
ctx.save();
|
|
235
|
+
ctx.shadowColor = shadowColor || '#000000';
|
|
236
|
+
ctx.shadowOffsetX = (shadowOffsetX || 0) * viewScaleInfo.scale;
|
|
237
|
+
ctx.shadowOffsetY = (shadowOffsetY || 0) * viewScaleInfo.scale;
|
|
238
|
+
ctx.shadowBlur = (shadowBlur || 0) * viewScaleInfo.scale;
|
|
239
|
+
renderContent();
|
|
240
|
+
ctx.restore();
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
renderContent();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { rotateElement } from '@idraw/util';
|
|
2
|
+
export function drawCircle(ctx, elem, opts) {
|
|
3
|
+
const { detail, angle } = elem;
|
|
4
|
+
const { background = '#000000', borderColor = '#000000', borderWidth = 0 } = detail;
|
|
5
|
+
const { calculator, viewScaleInfo, viewSizeInfo } = opts;
|
|
6
|
+
const { x, y, w, h } = calculator.elementSize({ x: elem.x, y: elem.y, w: elem.w, h: elem.h }, viewScaleInfo, viewSizeInfo);
|
|
7
|
+
rotateElement(ctx, { x, y, w, h, angle }, () => {
|
|
8
|
+
const a = w / 2;
|
|
9
|
+
const b = h / 2;
|
|
10
|
+
const centerX = x + a;
|
|
11
|
+
const centerY = y + b;
|
|
12
|
+
if (borderWidth && borderWidth > 0) {
|
|
13
|
+
const ba = borderWidth / 2 + a;
|
|
14
|
+
const bb = borderWidth / 2 + b;
|
|
15
|
+
ctx.beginPath();
|
|
16
|
+
ctx.strokeStyle = borderColor;
|
|
17
|
+
ctx.lineWidth = borderWidth;
|
|
18
|
+
ctx.circle(centerX, centerY, ba, bb, 0, 0, 2 * Math.PI);
|
|
19
|
+
ctx.closePath();
|
|
20
|
+
ctx.stroke();
|
|
21
|
+
}
|
|
22
|
+
ctx.beginPath();
|
|
23
|
+
ctx.fillStyle = background;
|
|
24
|
+
ctx.circle(centerX, centerY, a, b, 0, 0, 2 * Math.PI);
|
|
25
|
+
ctx.closePath();
|
|
26
|
+
ctx.fill();
|
|
27
|
+
});
|
|
28
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { drawElement } from './group';
|
|
2
|
+
export function drawElementList(ctx, data, opts) {
|
|
3
|
+
const { elements = [] } = data;
|
|
4
|
+
for (let i = 0; i < elements.length; i++) {
|
|
5
|
+
const elem = elements[i];
|
|
6
|
+
if (!opts.calculator.isElementInView(elem, opts.viewScaleInfo, opts.viewSizeInfo)) {
|
|
7
|
+
continue;
|
|
8
|
+
}
|
|
9
|
+
try {
|
|
10
|
+
drawElement(ctx, elem, opts);
|
|
11
|
+
}
|
|
12
|
+
catch (err) {
|
|
13
|
+
console.error(err);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { Element, ElementType, RendererDrawElementOptions, ViewContext2D } from '@idraw/types';
|
|
2
|
+
export declare function drawElement(ctx: ViewContext2D, elem: Element<ElementType>, opts: RendererDrawElementOptions): void;
|
|
3
|
+
export declare function drawGroup(ctx: ViewContext2D, elem: Element<'group'>, opts: RendererDrawElementOptions): void;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { rotateElement } from '@idraw/util';
|
|
2
|
+
import { drawCircle } from './circle';
|
|
3
|
+
import { drawRect } from './rect';
|
|
4
|
+
import { drawImage } from './image';
|
|
5
|
+
import { drawText } from './text';
|
|
6
|
+
import { drawSVG } from './svg';
|
|
7
|
+
import { drawHTML } from './html';
|
|
8
|
+
import { drawBox } from './base';
|
|
9
|
+
import { drawPath } from './path';
|
|
10
|
+
export function drawElement(ctx, elem, opts) {
|
|
11
|
+
var _a;
|
|
12
|
+
if (((_a = elem === null || elem === void 0 ? void 0 : elem.operations) === null || _a === void 0 ? void 0 : _a.invisible) === true) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
switch (elem.type) {
|
|
17
|
+
case 'rect': {
|
|
18
|
+
drawRect(ctx, elem, opts);
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
case 'circle': {
|
|
22
|
+
drawCircle(ctx, elem, opts);
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
case 'text': {
|
|
26
|
+
drawText(ctx, elem, opts);
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
case 'image': {
|
|
30
|
+
drawImage(ctx, elem, opts);
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
case 'svg': {
|
|
34
|
+
drawSVG(ctx, elem, opts);
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
case 'html': {
|
|
38
|
+
drawHTML(ctx, elem, opts);
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
case 'path': {
|
|
42
|
+
drawPath(ctx, elem, opts);
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
case 'group': {
|
|
46
|
+
drawGroup(ctx, elem, opts);
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
default: {
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
console.error(err);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export function drawGroup(ctx, elem, opts) {
|
|
59
|
+
const { calculator, viewScaleInfo, viewSizeInfo } = opts;
|
|
60
|
+
const { x, y, w, h, angle } = calculator.elementSize({ x: elem.x, y: elem.y, w: elem.w, h: elem.h, angle: elem.angle }, viewScaleInfo, viewSizeInfo);
|
|
61
|
+
const viewElem = Object.assign(Object.assign({}, elem), { x, y, w, h, angle });
|
|
62
|
+
rotateElement(ctx, { x, y, w, h, angle }, () => {
|
|
63
|
+
drawBox(ctx, viewElem, {
|
|
64
|
+
originElem: elem,
|
|
65
|
+
calcElemSize: { x, y, w, h, angle },
|
|
66
|
+
viewScaleInfo,
|
|
67
|
+
viewSizeInfo,
|
|
68
|
+
renderContent: () => {
|
|
69
|
+
if (Array.isArray(elem.detail.children)) {
|
|
70
|
+
const { parentElementSize: parentSize } = opts;
|
|
71
|
+
const newParentSize = {
|
|
72
|
+
x: parentSize.x + elem.x,
|
|
73
|
+
y: parentSize.y + elem.y,
|
|
74
|
+
w: elem.w || parentSize.w,
|
|
75
|
+
h: elem.h || parentSize.h,
|
|
76
|
+
angle: elem.angle
|
|
77
|
+
};
|
|
78
|
+
const { calculator } = opts;
|
|
79
|
+
if (elem.detail.overflow === 'hidden') {
|
|
80
|
+
ctx.save();
|
|
81
|
+
ctx.beginPath();
|
|
82
|
+
ctx.moveTo(x, y);
|
|
83
|
+
ctx.lineTo(x + w, y);
|
|
84
|
+
ctx.lineTo(x + w, y + h);
|
|
85
|
+
ctx.lineTo(x, y + h);
|
|
86
|
+
ctx.closePath();
|
|
87
|
+
ctx.clip();
|
|
88
|
+
}
|
|
89
|
+
for (let i = 0; i < elem.detail.children.length; i++) {
|
|
90
|
+
let child = elem.detail.children[i];
|
|
91
|
+
child = Object.assign(Object.assign({}, child), {
|
|
92
|
+
x: newParentSize.x + child.x,
|
|
93
|
+
y: newParentSize.y + child.y
|
|
94
|
+
});
|
|
95
|
+
if (!calculator.isElementInView(child, opts.viewScaleInfo, opts.viewSizeInfo)) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
drawElement(ctx, child, Object.assign({}, opts));
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
console.error(err);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
ctx.restore();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { rotateElement } from '@idraw/util';
|
|
2
|
+
export function drawHTML(ctx, elem, opts) {
|
|
3
|
+
const content = opts.loader.getContent(elem.uuid);
|
|
4
|
+
const { calculator, viewScaleInfo, viewSizeInfo } = opts;
|
|
5
|
+
const { x, y, w, h, angle } = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo);
|
|
6
|
+
rotateElement(ctx, { x, y, w, h, angle }, () => {
|
|
7
|
+
if (!content) {
|
|
8
|
+
opts.loader.load(elem);
|
|
9
|
+
}
|
|
10
|
+
if (elem.type === 'html' && content) {
|
|
11
|
+
ctx.drawImage(content, x, y, w, h);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { rotateElement } from '@idraw/util';
|
|
2
|
+
export function drawImage(ctx, elem, opts) {
|
|
3
|
+
const content = opts.loader.getContent(elem.uuid);
|
|
4
|
+
const { calculator, viewScaleInfo, viewSizeInfo } = opts;
|
|
5
|
+
const { x, y, w, h, angle } = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo);
|
|
6
|
+
rotateElement(ctx, { x, y, w, h, angle }, () => {
|
|
7
|
+
if (!content) {
|
|
8
|
+
opts.loader.load(elem, opts.elementAssets || {});
|
|
9
|
+
}
|
|
10
|
+
if (elem.type === 'image' && content) {
|
|
11
|
+
ctx.drawImage(content, x, y, w, h);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { drawCircle } from './circle';
|
|
2
|
+
export { drawRect } from './rect';
|
|
3
|
+
export { drawImage } from './image';
|
|
4
|
+
export { drawSVG } from './svg';
|
|
5
|
+
export { drawHTML } from './html';
|
|
6
|
+
export { drawText } from './text';
|
|
7
|
+
export { drawElementList } from './elements';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { drawCircle } from './circle';
|
|
2
|
+
export { drawRect } from './rect';
|
|
3
|
+
export { drawImage } from './image';
|
|
4
|
+
export { drawSVG } from './svg';
|
|
5
|
+
export { drawHTML } from './html';
|
|
6
|
+
export { drawText } from './text';
|
|
7
|
+
export { drawElementList } from './elements';
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { rotateElement, generateSVGPath } from '@idraw/util';
|
|
2
|
+
import { drawBox, drawBoxShadow } from './base';
|
|
3
|
+
export function drawPath(ctx, elem, opts) {
|
|
4
|
+
const { detail } = elem;
|
|
5
|
+
const { originX, originY, originW, originH } = detail;
|
|
6
|
+
const { calculator, viewScaleInfo, viewSizeInfo } = opts;
|
|
7
|
+
const { x, y, w, h, angle } = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo);
|
|
8
|
+
const scaleW = w / originW;
|
|
9
|
+
const scaleH = h / originH;
|
|
10
|
+
const viewOriginX = originX * scaleW;
|
|
11
|
+
const viewOriginY = originY * scaleH;
|
|
12
|
+
const internalX = x - viewOriginX;
|
|
13
|
+
const internalY = y - viewOriginY;
|
|
14
|
+
const scaleNum = viewScaleInfo.scale * viewSizeInfo.devicePixelRatio;
|
|
15
|
+
const viewElem = Object.assign(Object.assign({}, elem), { x, y, w, h, angle });
|
|
16
|
+
rotateElement(ctx, { x, y, w, h, angle }, () => {
|
|
17
|
+
drawBox(ctx, viewElem, {
|
|
18
|
+
originElem: elem,
|
|
19
|
+
calcElemSize: { x, y, w, h, angle },
|
|
20
|
+
viewScaleInfo,
|
|
21
|
+
viewSizeInfo,
|
|
22
|
+
renderContent: () => {
|
|
23
|
+
drawBoxShadow(ctx, viewElem, {
|
|
24
|
+
viewScaleInfo,
|
|
25
|
+
viewSizeInfo,
|
|
26
|
+
renderContent: () => {
|
|
27
|
+
ctx.save();
|
|
28
|
+
ctx.translate(internalX, internalY);
|
|
29
|
+
ctx.scale((scaleNum * scaleW) / viewScaleInfo.scale, (scaleNum * scaleH) / viewScaleInfo.scale);
|
|
30
|
+
const pathStr = generateSVGPath(detail.commands || []);
|
|
31
|
+
const path2d = new Path2D(pathStr);
|
|
32
|
+
if (detail.fill) {
|
|
33
|
+
ctx.fillStyle = detail.fill;
|
|
34
|
+
ctx.fill(path2d);
|
|
35
|
+
}
|
|
36
|
+
if (detail.stroke && detail.strokeWidth !== 0) {
|
|
37
|
+
ctx.strokeStyle = detail.stroke;
|
|
38
|
+
ctx.lineWidth = (detail.strokeWidth || 1) / viewSizeInfo.devicePixelRatio;
|
|
39
|
+
ctx.lineCap = detail.strokeLineCap || 'square';
|
|
40
|
+
ctx.stroke(path2d);
|
|
41
|
+
}
|
|
42
|
+
ctx.translate(-internalX, -internalY);
|
|
43
|
+
ctx.restore();
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { rotateElement } from '@idraw/util';
|
|
2
|
+
import { drawBox, drawBoxShadow } from './base';
|
|
3
|
+
export function drawRect(ctx, elem, opts) {
|
|
4
|
+
const { calculator, viewScaleInfo, viewSizeInfo } = opts;
|
|
5
|
+
let { x, y, w, h, angle } = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo);
|
|
6
|
+
const viewElem = Object.assign(Object.assign({}, elem), { x, y, w, h, angle });
|
|
7
|
+
rotateElement(ctx, { x, y, w, h, angle }, () => {
|
|
8
|
+
drawBoxShadow(ctx, viewElem, {
|
|
9
|
+
viewScaleInfo,
|
|
10
|
+
viewSizeInfo,
|
|
11
|
+
renderContent: () => {
|
|
12
|
+
drawBox(ctx, viewElem, {
|
|
13
|
+
originElem: elem,
|
|
14
|
+
calcElemSize: { x, y, w, h, angle },
|
|
15
|
+
viewScaleInfo,
|
|
16
|
+
viewSizeInfo,
|
|
17
|
+
renderContent: () => {
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { rotateElement } from '@idraw/util';
|
|
2
|
+
export function drawSVG(ctx, elem, opts) {
|
|
3
|
+
const content = opts.loader.getContent(elem.uuid);
|
|
4
|
+
const { calculator, viewScaleInfo, viewSizeInfo } = opts;
|
|
5
|
+
const { x, y, w, h, angle } = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo);
|
|
6
|
+
rotateElement(ctx, { x, y, w, h, angle }, () => {
|
|
7
|
+
if (!content) {
|
|
8
|
+
opts.loader.load(elem, opts.elementAssets || {});
|
|
9
|
+
}
|
|
10
|
+
if (elem.type === 'svg' && content) {
|
|
11
|
+
ctx.drawImage(content, x, y, w, h);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
}
|