@codehz/draw-call 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +374 -6
- package/{canvas-BYrCq8eS.d.mts → canvas.d.cts} +145 -34
- package/{canvas-CkpP3RNK.d.cts → canvas.d.mts} +145 -34
- package/examples/card.ts +155 -0
- package/examples/demo.ts +478 -0
- package/examples/richtext.ts +284 -0
- package/index.cjs +139 -9
- package/index.d.cts +51 -2
- package/index.d.mts +51 -2
- package/index.mjs +127 -3
- package/node.cjs +8 -7
- package/node.d.cts +3 -3
- package/node.d.mts +3 -3
- package/node.mjs +7 -6
- package/package.json +1 -1
- package/render.cjs +1555 -0
- package/render.mjs +1531 -0
- package/engine-C88lMGbX.mjs +0 -606
- package/engine-OyKoV7Gn.cjs +0 -636
package/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as radialGradient, i as linearGradient, n as computeLayout, r as createCanvasMeasureContext, t as renderNode } from "./
|
|
1
|
+
import { a as radialGradient, i as linearGradient, n as computeLayout, r as createCanvasMeasureContext, t as renderNode } from "./render.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/canvas.ts
|
|
4
4
|
/**
|
|
@@ -24,6 +24,7 @@ function createCanvas(options) {
|
|
|
24
24
|
width,
|
|
25
25
|
height,
|
|
26
26
|
pixelRatio,
|
|
27
|
+
canvas,
|
|
27
28
|
render(element) {
|
|
28
29
|
const layoutTree = computeLayout(element, measureCtx, {
|
|
29
30
|
minWidth: 0,
|
|
@@ -44,7 +45,7 @@ function createCanvas(options) {
|
|
|
44
45
|
if ("toDataURL" in canvas && typeof canvas.toDataURL === "function") return canvas.toDataURL(type, quality);
|
|
45
46
|
throw new Error("toDataURL not supported");
|
|
46
47
|
},
|
|
47
|
-
|
|
48
|
+
toBuffer(type = "image/png") {
|
|
48
49
|
if ("toBuffer" in canvas && typeof canvas.toBuffer === "function") return canvas.toBuffer(type);
|
|
49
50
|
throw new Error("toBuffer not supported in this environment");
|
|
50
51
|
}
|
|
@@ -60,6 +61,24 @@ function Box(props) {
|
|
|
60
61
|
};
|
|
61
62
|
}
|
|
62
63
|
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/components/Image.ts
|
|
66
|
+
function Image(props) {
|
|
67
|
+
return {
|
|
68
|
+
type: "image",
|
|
69
|
+
...props
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/components/RichText.ts
|
|
75
|
+
function RichText(props) {
|
|
76
|
+
return {
|
|
77
|
+
type: "richtext",
|
|
78
|
+
...props
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
63
82
|
//#endregion
|
|
64
83
|
//#region src/components/Stack.ts
|
|
65
84
|
function Stack(props) {
|
|
@@ -69,6 +88,53 @@ function Stack(props) {
|
|
|
69
88
|
};
|
|
70
89
|
}
|
|
71
90
|
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region src/components/Svg.ts
|
|
93
|
+
function Svg(props) {
|
|
94
|
+
return {
|
|
95
|
+
type: "svg",
|
|
96
|
+
...props
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const svg = {
|
|
100
|
+
rect: (props) => ({
|
|
101
|
+
type: "rect",
|
|
102
|
+
...props
|
|
103
|
+
}),
|
|
104
|
+
circle: (props) => ({
|
|
105
|
+
type: "circle",
|
|
106
|
+
...props
|
|
107
|
+
}),
|
|
108
|
+
ellipse: (props) => ({
|
|
109
|
+
type: "ellipse",
|
|
110
|
+
...props
|
|
111
|
+
}),
|
|
112
|
+
line: (props) => ({
|
|
113
|
+
type: "line",
|
|
114
|
+
...props
|
|
115
|
+
}),
|
|
116
|
+
polyline: (props) => ({
|
|
117
|
+
type: "polyline",
|
|
118
|
+
...props
|
|
119
|
+
}),
|
|
120
|
+
polygon: (props) => ({
|
|
121
|
+
type: "polygon",
|
|
122
|
+
...props
|
|
123
|
+
}),
|
|
124
|
+
path: (props) => ({
|
|
125
|
+
type: "path",
|
|
126
|
+
...props
|
|
127
|
+
}),
|
|
128
|
+
text: (props) => ({
|
|
129
|
+
type: "text",
|
|
130
|
+
...props
|
|
131
|
+
}),
|
|
132
|
+
g: (props) => ({
|
|
133
|
+
type: "g",
|
|
134
|
+
...props
|
|
135
|
+
})
|
|
136
|
+
};
|
|
137
|
+
|
|
72
138
|
//#endregion
|
|
73
139
|
//#region src/components/Text.ts
|
|
74
140
|
function Text(props) {
|
|
@@ -79,4 +145,62 @@ function Text(props) {
|
|
|
79
145
|
}
|
|
80
146
|
|
|
81
147
|
//#endregion
|
|
82
|
-
|
|
148
|
+
//#region src/layout/utils/print.ts
|
|
149
|
+
/**
|
|
150
|
+
* 获取元素类型的显示名称
|
|
151
|
+
*/
|
|
152
|
+
function getElementType(element) {
|
|
153
|
+
switch (element.type) {
|
|
154
|
+
case "box": return "Box";
|
|
155
|
+
case "text": return `Text "${element.content.slice(0, 20)}${element.content.length > 20 ? "..." : ""}"`;
|
|
156
|
+
case "stack": return "Stack";
|
|
157
|
+
case "image": return "Image";
|
|
158
|
+
case "svg": return "Svg";
|
|
159
|
+
default: return element.type;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* 递归打印布局树
|
|
164
|
+
*/
|
|
165
|
+
function printLayoutToString(node, prefix = "", isLast = true, depth = 0) {
|
|
166
|
+
const lines = [];
|
|
167
|
+
const connector = isLast ? "└─ " : "├─ ";
|
|
168
|
+
const type = getElementType(node.element);
|
|
169
|
+
const { x, y, width, height } = node.layout;
|
|
170
|
+
const childCount = node.children.length;
|
|
171
|
+
lines.push(`${prefix}${connector}${type} @(${Math.round(x)},${Math.round(y)}) size:${Math.round(width)}x${Math.round(height)}`);
|
|
172
|
+
if (node.element.type === "text" && node.lines) {
|
|
173
|
+
const contentPrefix = prefix + (isLast ? " " : "│ ");
|
|
174
|
+
for (let i = 0; i < node.lines.length; i++) {
|
|
175
|
+
const lineText = node.lines[i];
|
|
176
|
+
const isLastLine = i === node.lines.length - 1 && childCount === 0;
|
|
177
|
+
lines.push(`${contentPrefix}${isLastLine ? "└─ " : "├─ "}${JSON.stringify(lineText)}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
181
|
+
const child = node.children[i];
|
|
182
|
+
const isChildLast = i === node.children.length - 1;
|
|
183
|
+
const childPrefix = prefix + (isLast ? " " : "│ ");
|
|
184
|
+
lines.push(...printLayoutToString(child, childPrefix, isChildLast, depth + 1));
|
|
185
|
+
}
|
|
186
|
+
return lines;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* 打印 LayoutNode 树结构到控制台
|
|
190
|
+
*/
|
|
191
|
+
function printLayout(node) {
|
|
192
|
+
const lines = printLayoutToString(node, "", true);
|
|
193
|
+
console.log(lines.join("\n"));
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* 将 LayoutNode 转换为美观的字符串
|
|
197
|
+
* @param node LayoutNode 根节点
|
|
198
|
+
* @param indent 缩进字符串,默认为两个空格
|
|
199
|
+
* @returns 格式化的字符串
|
|
200
|
+
*/
|
|
201
|
+
function layoutToString(node, _indent = " ") {
|
|
202
|
+
return printLayoutToString(node, "", true).join("\n");
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
//#endregion
|
|
206
|
+
export { Box, Image, RichText, Stack, Svg, Text, computeLayout, createCanvas, createCanvasMeasureContext, layoutToString, linearGradient, printLayout, radialGradient, svg };
|
package/node.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const require_render = require('./render.cjs');
|
|
2
2
|
let _napi_rs_canvas = require("@napi-rs/canvas");
|
|
3
3
|
|
|
4
4
|
//#region src/node.ts
|
|
@@ -8,24 +8,25 @@ let _napi_rs_canvas = require("@napi-rs/canvas");
|
|
|
8
8
|
* 此函数需要 @napi-rs/canvas 作为依赖
|
|
9
9
|
* 安装: bun add @napi-rs/canvas
|
|
10
10
|
*/
|
|
11
|
-
function
|
|
11
|
+
function createNodeCanvas(options) {
|
|
12
12
|
const { width, height, pixelRatio = 1 } = options;
|
|
13
13
|
const canvas = (0, _napi_rs_canvas.createCanvas)(width * pixelRatio, height * pixelRatio);
|
|
14
14
|
const ctx = canvas.getContext("2d");
|
|
15
15
|
if (pixelRatio !== 1) ctx.scale(pixelRatio, pixelRatio);
|
|
16
|
-
const measureCtx =
|
|
16
|
+
const measureCtx = require_render.createCanvasMeasureContext(ctx);
|
|
17
17
|
return {
|
|
18
18
|
width,
|
|
19
19
|
height,
|
|
20
20
|
pixelRatio,
|
|
21
|
+
canvas,
|
|
21
22
|
render(element) {
|
|
22
|
-
const layoutTree =
|
|
23
|
+
const layoutTree = require_render.computeLayout(element, measureCtx, {
|
|
23
24
|
minWidth: 0,
|
|
24
25
|
maxWidth: width,
|
|
25
26
|
minHeight: 0,
|
|
26
27
|
maxHeight: height
|
|
27
28
|
});
|
|
28
|
-
|
|
29
|
+
require_render.renderNode(ctx, layoutTree);
|
|
29
30
|
return layoutTree;
|
|
30
31
|
},
|
|
31
32
|
clear() {
|
|
@@ -37,11 +38,11 @@ function createCanvas(options) {
|
|
|
37
38
|
toDataURL(type, quality) {
|
|
38
39
|
return canvas.toDataURL(type, quality);
|
|
39
40
|
},
|
|
40
|
-
|
|
41
|
+
toBuffer(type = "image/png") {
|
|
41
42
|
return canvas.toBuffer(type);
|
|
42
43
|
}
|
|
43
44
|
};
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
//#endregion
|
|
47
|
-
exports.
|
|
48
|
+
exports.createNodeCanvas = createNodeCanvas;
|
package/node.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as DrawCallCanvas, t as CanvasOptions } from "./canvas
|
|
1
|
+
import { n as DrawCallCanvas, t as CanvasOptions } from "./canvas.cjs";
|
|
2
2
|
|
|
3
3
|
//#region src/node.d.ts
|
|
4
4
|
/**
|
|
@@ -7,6 +7,6 @@ import { n as DrawCallCanvas, t as CanvasOptions } from "./canvas-CkpP3RNK.cjs";
|
|
|
7
7
|
* 此函数需要 @napi-rs/canvas 作为依赖
|
|
8
8
|
* 安装: bun add @napi-rs/canvas
|
|
9
9
|
*/
|
|
10
|
-
declare function
|
|
10
|
+
declare function createNodeCanvas(options: Omit<CanvasOptions, "canvas">): DrawCallCanvas;
|
|
11
11
|
//#endregion
|
|
12
|
-
export {
|
|
12
|
+
export { createNodeCanvas };
|
package/node.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as DrawCallCanvas, t as CanvasOptions } from "./canvas
|
|
1
|
+
import { n as DrawCallCanvas, t as CanvasOptions } from "./canvas.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/node.d.ts
|
|
4
4
|
/**
|
|
@@ -7,6 +7,6 @@ import { n as DrawCallCanvas, t as CanvasOptions } from "./canvas-BYrCq8eS.mjs";
|
|
|
7
7
|
* 此函数需要 @napi-rs/canvas 作为依赖
|
|
8
8
|
* 安装: bun add @napi-rs/canvas
|
|
9
9
|
*/
|
|
10
|
-
declare function
|
|
10
|
+
declare function createNodeCanvas(options: Omit<CanvasOptions, "canvas">): DrawCallCanvas;
|
|
11
11
|
//#endregion
|
|
12
|
-
export {
|
|
12
|
+
export { createNodeCanvas };
|
package/node.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as computeLayout, r as createCanvasMeasureContext, t as renderNode } from "./
|
|
2
|
-
import { createCanvas
|
|
1
|
+
import { n as computeLayout, r as createCanvasMeasureContext, t as renderNode } from "./render.mjs";
|
|
2
|
+
import { createCanvas } from "@napi-rs/canvas";
|
|
3
3
|
|
|
4
4
|
//#region src/node.ts
|
|
5
5
|
/**
|
|
@@ -8,9 +8,9 @@ import { createCanvas as createCanvas$1 } from "@napi-rs/canvas";
|
|
|
8
8
|
* 此函数需要 @napi-rs/canvas 作为依赖
|
|
9
9
|
* 安装: bun add @napi-rs/canvas
|
|
10
10
|
*/
|
|
11
|
-
function
|
|
11
|
+
function createNodeCanvas(options) {
|
|
12
12
|
const { width, height, pixelRatio = 1 } = options;
|
|
13
|
-
const canvas = createCanvas
|
|
13
|
+
const canvas = createCanvas(width * pixelRatio, height * pixelRatio);
|
|
14
14
|
const ctx = canvas.getContext("2d");
|
|
15
15
|
if (pixelRatio !== 1) ctx.scale(pixelRatio, pixelRatio);
|
|
16
16
|
const measureCtx = createCanvasMeasureContext(ctx);
|
|
@@ -18,6 +18,7 @@ function createCanvas(options) {
|
|
|
18
18
|
width,
|
|
19
19
|
height,
|
|
20
20
|
pixelRatio,
|
|
21
|
+
canvas,
|
|
21
22
|
render(element) {
|
|
22
23
|
const layoutTree = computeLayout(element, measureCtx, {
|
|
23
24
|
minWidth: 0,
|
|
@@ -37,11 +38,11 @@ function createCanvas(options) {
|
|
|
37
38
|
toDataURL(type, quality) {
|
|
38
39
|
return canvas.toDataURL(type, quality);
|
|
39
40
|
},
|
|
40
|
-
|
|
41
|
+
toBuffer(type = "image/png") {
|
|
41
42
|
return canvas.toBuffer(type);
|
|
42
43
|
}
|
|
43
44
|
};
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
//#endregion
|
|
47
|
-
export {
|
|
48
|
+
export { createNodeCanvas };
|