@codehz/draw-call 0.5.2 → 0.6.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.
@@ -3,7 +3,7 @@
3
3
  * 展示直接调用 Canvas API、Transform 管理和子元素渲染功能
4
4
  * 运行: bun examples/customdraw.ts
5
5
  */
6
- import { Box, createCanvas, CustomDraw, printLayout, Text } from "@codehz/draw-call";
6
+ import { Box, createCanvas, CustomDraw, printLayout, Text } from "@/index";
7
7
  import { GlobalFonts } from "@napi-rs/canvas";
8
8
  import { fileURLToPath } from "bun";
9
9
 
@@ -23,6 +23,7 @@ function PieChart(data: Array<{ label: string; value: number; color: string }>)
23
23
  width: 200,
24
24
  height: 200,
25
25
  draw(ctx, { width, height }) {
26
+ const canvas = ctx.canvas;
26
27
  const centerX = width / 2;
27
28
  const centerY = height / 2;
28
29
  const radius = Math.min(width, height) / 2 - 5;
@@ -33,17 +34,17 @@ function PieChart(data: Array<{ label: string; value: number; color: string }>)
33
34
  const sliceAngle = (item.value / total) * Math.PI * 2;
34
35
 
35
36
  // 绘制扇形
36
- ctx.beginPath();
37
- ctx.moveTo(centerX, centerY);
38
- ctx.arc(centerX, centerY, radius, currentAngle, currentAngle + sliceAngle);
39
- ctx.closePath();
40
- ctx.fillStyle = item.color;
41
- ctx.fill();
37
+ canvas.beginPath();
38
+ canvas.moveTo(centerX, centerY);
39
+ canvas.arc(centerX, centerY, radius, currentAngle, currentAngle + sliceAngle);
40
+ canvas.closePath();
41
+ canvas.fillStyle = item.color;
42
+ canvas.fill();
42
43
 
43
44
  // 绘制边框
44
- ctx.strokeStyle = "#ffffff";
45
- ctx.lineWidth = 2;
46
- ctx.stroke();
45
+ canvas.strokeStyle = "#ffffff";
46
+ canvas.lineWidth = 2;
47
+ canvas.stroke();
47
48
 
48
49
  currentAngle += sliceAngle;
49
50
  }
@@ -57,25 +58,26 @@ function GridBackground() {
57
58
  width: 100,
58
59
  height: 100,
59
60
  draw(ctx, { width, height }) {
61
+ const canvas = ctx.canvas;
60
62
  const gridSize = 20;
61
63
 
62
- ctx.strokeStyle = "rgba(200, 200, 200, 0.3)";
63
- ctx.lineWidth = 1;
64
+ canvas.strokeStyle = "rgba(200, 200, 200, 0.3)";
65
+ canvas.lineWidth = 1;
64
66
 
65
67
  // 绘制垂直线
66
68
  for (let x = 0; x <= width; x += gridSize) {
67
- ctx.beginPath();
68
- ctx.moveTo(x, 0);
69
- ctx.lineTo(x, height);
70
- ctx.stroke();
69
+ canvas.beginPath();
70
+ canvas.moveTo(x, 0);
71
+ canvas.lineTo(x, height);
72
+ canvas.stroke();
71
73
  }
72
74
 
73
75
  // 绘制水平线
74
76
  for (let y = 0; y <= height; y += gridSize) {
75
- ctx.beginPath();
76
- ctx.moveTo(0, y);
77
- ctx.lineTo(width, y);
78
- ctx.stroke();
77
+ canvas.beginPath();
78
+ canvas.moveTo(0, y);
79
+ canvas.lineTo(width, y);
80
+ canvas.stroke();
79
81
  }
80
82
  },
81
83
  });
@@ -87,30 +89,31 @@ function ProgressRing(percentage: number, color: string) {
87
89
  width: 120,
88
90
  height: 120,
89
91
  draw(ctx, { inner, width, height }) {
92
+ const canvas = ctx.canvas;
90
93
  const centerX = width / 2;
91
94
  const centerY = height / 2;
92
95
  const radius = Math.min(width, height) / 2 - 8;
93
96
 
94
97
  // 绘制背景圆
95
- ctx.strokeStyle = "rgba(0, 0, 0, 0.1)";
96
- ctx.lineWidth = 8;
97
- ctx.beginPath();
98
- ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);
99
- ctx.stroke();
98
+ canvas.strokeStyle = "rgba(0, 0, 0, 0.1)";
99
+ canvas.lineWidth = 8;
100
+ canvas.beginPath();
101
+ canvas.arc(centerX, centerY, radius, 0, Math.PI * 2);
102
+ canvas.stroke();
100
103
 
101
104
  // 绘制进度圆
102
105
  const endAngle = (percentage / 100) * Math.PI * 2 - Math.PI / 2;
103
- ctx.strokeStyle = color;
104
- ctx.lineCap = "round";
105
- ctx.beginPath();
106
- ctx.arc(centerX, centerY, radius, -Math.PI / 2, endAngle);
107
- ctx.stroke();
106
+ canvas.strokeStyle = color;
107
+ canvas.lineCap = "round";
108
+ canvas.beginPath();
109
+ canvas.arc(centerX, centerY, radius, -Math.PI / 2, endAngle);
110
+ canvas.stroke();
108
111
 
109
112
  // 绘制百分比文本的背景
110
113
  ctx.save();
111
- ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
112
- ctx.globalAlpha = 0.1;
113
- ctx.fillRect(centerX - 30, centerY - 20, 60, 40);
114
+ canvas.fillStyle = "rgba(0, 0, 0, 0.5)";
115
+ canvas.globalAlpha = 0.1;
116
+ canvas.fillRect(centerX - 30, centerY - 20, 60, 40);
114
117
  ctx.restore();
115
118
 
116
119
  inner?.();
@@ -139,6 +142,7 @@ function LineChart() {
139
142
  width: 300,
140
143
  height: 150,
141
144
  draw(ctx, { width, height }) {
145
+ const canvas = ctx.canvas;
142
146
  const padding = 10;
143
147
  const graphWidth = width - padding * 2;
144
148
  const graphHeight = height - padding * 2;
@@ -147,61 +151,61 @@ function LineChart() {
147
151
  const pointSpacing = graphWidth / (data.length - 1);
148
152
 
149
153
  // 绘制网格线
150
- ctx.strokeStyle = "rgba(200, 200, 200, 0.2)";
151
- ctx.lineWidth = 1;
154
+ canvas.strokeStyle = "rgba(200, 200, 200, 0.2)";
155
+ canvas.lineWidth = 1;
152
156
  for (let i = 0; i <= 4; i++) {
153
157
  const y = padding + (graphHeight / 4) * i;
154
- ctx.beginPath();
155
- ctx.moveTo(padding, y);
156
- ctx.lineTo(width - padding, y);
157
- ctx.stroke();
158
+ canvas.beginPath();
159
+ canvas.moveTo(padding, y);
160
+ canvas.lineTo(width - padding, y);
161
+ canvas.stroke();
158
162
  }
159
163
 
160
164
  // 绘制折线
161
- ctx.strokeStyle = "#667eea";
162
- ctx.lineWidth = 2;
163
- ctx.beginPath();
165
+ canvas.strokeStyle = "#667eea";
166
+ canvas.lineWidth = 2;
167
+ canvas.beginPath();
164
168
 
165
169
  for (let i = 0; i < data.length; i++) {
166
170
  const x = padding + i * pointSpacing;
167
171
  const y = height - padding - (data[i] / maxValue) * graphHeight;
168
172
 
169
173
  if (i === 0) {
170
- ctx.moveTo(x, y);
174
+ canvas.moveTo(x, y);
171
175
  } else {
172
- ctx.lineTo(x, y);
176
+ canvas.lineTo(x, y);
173
177
  }
174
178
  }
175
179
 
176
- ctx.stroke();
180
+ canvas.stroke();
177
181
 
178
182
  // 绘制数据点
179
- ctx.fillStyle = "#667eea";
183
+ canvas.fillStyle = "#667eea";
180
184
  for (let i = 0; i < data.length; i++) {
181
185
  const x = padding + i * pointSpacing;
182
186
  const y = height - padding - (data[i] / maxValue) * graphHeight;
183
187
 
184
- ctx.beginPath();
185
- ctx.arc(x, y, 3, 0, Math.PI * 2);
186
- ctx.fill();
188
+ canvas.beginPath();
189
+ canvas.arc(x, y, 3, 0, Math.PI * 2);
190
+ canvas.fill();
187
191
  }
188
192
 
189
193
  // 绘制阴影
190
194
  ctx.save();
191
- ctx.globalAlpha = 0.2;
192
- ctx.fillStyle = "#667eea";
193
- ctx.beginPath();
194
- ctx.moveTo(padding, height - padding);
195
+ canvas.globalAlpha = 0.2;
196
+ canvas.fillStyle = "#667eea";
197
+ canvas.beginPath();
198
+ canvas.moveTo(padding, height - padding);
195
199
 
196
200
  for (let i = 0; i < data.length; i++) {
197
201
  const x = padding + i * pointSpacing;
198
202
  const y = height - padding - (data[i] / maxValue) * graphHeight;
199
- ctx.lineTo(x, y);
203
+ canvas.lineTo(x, y);
200
204
  }
201
205
 
202
- ctx.lineTo(width - padding, height - padding);
203
- ctx.closePath();
204
- ctx.fill();
206
+ canvas.lineTo(width - padding, height - padding);
207
+ canvas.closePath();
208
+ canvas.fill();
205
209
  ctx.restore();
206
210
  },
207
211
  });
@@ -224,7 +228,7 @@ const layout = canvas.render(
224
228
  }),
225
229
 
226
230
  Text({
227
- content: "直接调用 Canvas API 进行自定义绘制,同时支持可选的子元素",
231
+ content: "通过 ctx.canvas 调用原生 Canvas API,同时支持受控 transform 和可选子元素",
228
232
  font: { size: 14, family: "unifont" },
229
233
  color: "#666666",
230
234
  }),
@@ -235,7 +239,7 @@ const layout = canvas.render(
235
239
  gap: 10,
236
240
  children: [
237
241
  Text({
238
- content: "1. 网格背景 + 直接 Canvas 绘制",
242
+ content: "1. 网格背景 + ctx.canvas 绘制",
239
243
  font: { size: 16, weight: "bold", family: "unifont" },
240
244
  color: "#666666",
241
245
  }),
@@ -0,0 +1,114 @@
1
+ <!doctype html>
2
+ <html lang="zh">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>draw-call 演示</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ font-family:
16
+ -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
17
+ "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
18
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
19
+ min-height: 100vh;
20
+ display: flex;
21
+ align-items: center;
22
+ justify-content: center;
23
+ padding: 20px;
24
+ }
25
+
26
+ .container {
27
+ background: white;
28
+ border-radius: 16px;
29
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
30
+ padding: 40px;
31
+ max-width: 860px;
32
+ width: 100%;
33
+ }
34
+
35
+ h1 {
36
+ margin-bottom: 10px;
37
+ color: #333;
38
+ font-size: 28px;
39
+ }
40
+
41
+ .subtitle {
42
+ color: #666;
43
+ margin-bottom: 30px;
44
+ font-size: 14px;
45
+ }
46
+
47
+ .canvas-wrapper {
48
+ background: #f9f9f9;
49
+ border-radius: 12px;
50
+ padding: 20px;
51
+ border: 1px solid #e0e0e0;
52
+ display: flex;
53
+ justify-content: center;
54
+ align-items: center;
55
+ margin-bottom: 30px;
56
+ min-height: 420px;
57
+ }
58
+
59
+ canvas {
60
+ max-width: 100%;
61
+ height: auto;
62
+ border-radius: 8px;
63
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
64
+ }
65
+
66
+ .features {
67
+ display: grid;
68
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
69
+ gap: 15px;
70
+ margin-top: 30px;
71
+ }
72
+
73
+ .feature-item {
74
+ background: #f5f5f5;
75
+ padding: 12px;
76
+ border-radius: 8px;
77
+ font-size: 12px;
78
+ color: #666;
79
+ border-left: 3px solid #667eea;
80
+ }
81
+
82
+ .feature-item strong {
83
+ color: #333;
84
+ }
85
+
86
+ .loading {
87
+ text-align: center;
88
+ color: #999;
89
+ font-size: 14px;
90
+ }
91
+ </style>
92
+ </head>
93
+ <body>
94
+ <div class="container">
95
+ <h1>🎨 draw-call 演示</h1>
96
+ <p class="subtitle">使用声明式 Canvas 绘图库展示现代 UI 绘制能力</p>
97
+
98
+ <div class="canvas-wrapper">
99
+ <canvas id="canvas"></canvas>
100
+ </div>
101
+
102
+ <div class="features">
103
+ <div class="feature-item"><strong>📐 Flexbox 布局</strong><br />支持现代化布局引擎</div>
104
+ <div class="feature-item"><strong>🎨 丰富样式</strong><br />背景、边框、阴影、渐变等</div>
105
+ <div class="feature-item"><strong>📝 文本排版</strong><br />支持换行、对齐、字体自定义</div>
106
+ <div class="feature-item"><strong>🎯 声明式 API</strong><br />类似 React 的组件化方式</div>
107
+ <div class="feature-item"><strong>✨ 高清显示</strong><br />支持高 DPI 设备自适应</div>
108
+ <div class="feature-item"><strong>🚀 TypeScript</strong><br />完整的类型支持和开发体验</div>
109
+ </div>
110
+ </div>
111
+
112
+ <script src="demo.ts"></script>
113
+ </body>
114
+ </html>
package/examples/demo.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * draw-call 网页演示
3
3
  * 展示库的各项功能:逐句布局、样式、文本排版、图片渲染等
4
4
  */
5
- import { Box, createCanvas, Image, linearGradient, Svg, svg, Text } from "@codehz/draw-call";
5
+ import { Box, createCanvas, Image, linearGradient, Svg, svg, Text } from "@/index";
6
6
 
7
7
  // 创建一个 canvas 并绘制图片内容,返回用于 Image 组件的 canvas
8
8
  function createDemoImage(): HTMLCanvasElement {
@@ -1,4 +1,4 @@
1
- import { Box, createCanvas } from "@codehz/draw-call";
1
+ import { Box, createCanvas } from "@/index";
2
2
 
3
3
  // 创建 Canvas,禁用图像平滑
4
4
  const canvas1 = createCanvas({
@@ -2,7 +2,7 @@
2
2
  * 示例:使用 draw-call 的 RichText 组件
3
3
  * 运行: bun examples/richtext.ts
4
4
  */
5
- import { Box, createCanvas, RichText, Text } from "@codehz/draw-call";
5
+ import { Box, createCanvas, RichText, Text } from "@/index";
6
6
  import { GlobalFonts } from "@napi-rs/canvas";
7
7
  import { fileURLToPath } from "bun";
8
8
 
@@ -3,7 +3,7 @@
3
3
  * 展示移动(translate)、旋转(rotate)、放大(scale)等变换效果
4
4
  * 运行: bun examples/transform.ts
5
5
  */
6
- import { Box, createCanvas, printLayout, Text, Transform } from "@codehz/draw-call";
6
+ import { Box, createCanvas, printLayout, Text, Transform } from "@/index";
7
7
  import { GlobalFonts } from "@napi-rs/canvas";
8
8
  import { fileURLToPath } from "bun";
9
9
 
package/package.json CHANGED
@@ -1,47 +1,70 @@
1
1
  {
2
2
  "name": "@codehz/draw-call",
3
- "module": "./node/index.mjs",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
+ "main": "./dist/node/index.cjs",
6
+ "module": "./dist/node/index.mjs",
7
+ "types": "./dist/node/index.d.mts",
8
+ "exports": {
9
+ ".": {
10
+ "browser": {
11
+ "types": "./dist/browser/index.d.ts",
12
+ "import": "./dist/browser/index.js",
13
+ "require": "./dist/browser/index.cjs"
14
+ },
15
+ "bun": {
16
+ "types": "./dist/node/index.d.mts",
17
+ "import": "./dist/node/index.mjs"
18
+ },
19
+ "types": "./dist/node/index.d.mts",
20
+ "import": "./dist/node/index.mjs",
21
+ "require": "./dist/node/index.cjs"
22
+ }
23
+ },
24
+ "files": [
25
+ "dist",
26
+ "examples",
27
+ "README.md",
28
+ "LICENSE"
29
+ ],
5
30
  "repository": {
6
31
  "type": "git",
7
32
  "url": "https://github.com/codehz/draw-call.git"
8
33
  },
34
+ "scripts": {
35
+ "lint": "eslint --ext .ts,.tsx,.js --quiet",
36
+ "lint:fix": "eslint --ext .ts,.tsx,.js --fix",
37
+ "format": "prettier --write .",
38
+ "test": "bun test",
39
+ "release": "bun scripts/release.ts",
40
+ "prepare": "husky"
41
+ },
42
+ "lint-staged": {
43
+ "*.{ts,tsx}": [
44
+ "prettier --write",
45
+ "eslint --fix"
46
+ ],
47
+ "*.{json,md}": [
48
+ "prettier --write"
49
+ ]
50
+ },
9
51
  "devDependencies": {
10
52
  "@fontpkg/unifont": "^15.0.1",
11
- "@types/bun": "latest",
12
- "@typescript-eslint/eslint-plugin": "^8.0.0",
13
- "@typescript-eslint/parser": "^8.0.0",
14
- "eslint": "^9.0.0",
15
- "eslint-plugin-prettier": "^5.0.0",
16
- "husky": "^9.0.0",
17
- "lint-staged": "^15.0.0",
18
- "prettier": "^3.0.0",
19
- "prettier-plugin-organize-imports": "^4.0.0",
20
- "tsdown": "^0.21.0-beta.2"
53
+ "@types/bun": "^1.3.13",
54
+ "@typescript-eslint/eslint-plugin": "^8.59.2",
55
+ "@typescript-eslint/parser": "^8.59.2",
56
+ "eslint": "^10.3.0",
57
+ "eslint-plugin-prettier": "^5.5.5",
58
+ "husky": "^9.1.7",
59
+ "lint-staged": "^17.0.2",
60
+ "prettier": "^3.8.3",
61
+ "prettier-plugin-organize-imports": "^4.3.0",
62
+ "tsdown": "^0.22.0"
21
63
  },
22
64
  "peerDependencies": {
23
- "typescript": "^5"
65
+ "typescript": "^6.0.3"
24
66
  },
25
67
  "optionalDependencies": {
26
- "@napi-rs/canvas": "^0.1.88"
27
- },
28
- "version": "0.5.2",
29
- "main": "./node/index.cjs",
30
- "types": "./node/index.d.cts",
31
- "exports": {
32
- ".": {
33
- "browser": {
34
- "types": "./browser/index.d.ts",
35
- "import": "./browser/index.js",
36
- "require": "./browser/index.cjs"
37
- },
38
- "bun": {
39
- "types": "./node/index.d.mts",
40
- "import": "./node/index.mjs"
41
- },
42
- "types": "./node/index.d.mts",
43
- "import": "./node/index.mjs",
44
- "require": "./node/index.cjs"
45
- }
68
+ "@napi-rs/canvas": "^1.0.0"
46
69
  }
47
70
  }