@codehz/draw-call 0.5.3 → 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.
@@ -20,13 +20,14 @@ const SimpleRect = CustomDraw({
20
20
  width: 150,
21
21
  height: 80,
22
22
  draw(ctx, { width, height }) {
23
- ctx.fillStyle = "#667eea";
24
- ctx.fillRect(0, 0, width, height);
25
- ctx.fillStyle = "#000000";
26
- ctx.font = "bold 16px sans-serif";
27
- ctx.textAlign = "center";
28
- ctx.textBaseline = "middle";
29
- ctx.fillText("Simple Rect", width / 2, height / 2);
23
+ const canvas = ctx.canvas;
24
+ canvas.fillStyle = "#667eea";
25
+ canvas.fillRect(0, 0, width, height);
26
+ canvas.fillStyle = "#000000";
27
+ canvas.font = "bold 16px sans-serif";
28
+ canvas.textAlign = "center";
29
+ canvas.textBaseline = "middle";
30
+ canvas.fillText("Simple Rect", width / 2, height / 2);
30
31
  },
31
32
  });
32
33
 
@@ -35,20 +36,21 @@ const RotatedRect = CustomDraw({
35
36
  width: 150,
36
37
  height: 80,
37
38
  draw(ctx, { width, height }) {
39
+ const canvas = ctx.canvas;
38
40
  // save/restore 会自动平衡,即使不显式调用也能正确恢复
39
41
  ctx.save();
40
42
  ctx.translate(width / 2, height / 2);
41
43
  ctx.rotate((Math.PI / 4) * 0.3); // 15 度
42
- ctx.fillStyle = "#764ba2";
43
- ctx.fillRect(-width / 2, -height / 2, width, height);
44
+ canvas.fillStyle = "#764ba2";
45
+ canvas.fillRect(-width / 2, -height / 2, width, height);
44
46
  ctx.restore();
45
47
 
46
48
  // 恢复后可以正常绘制
47
- ctx.fillStyle = "#000000";
48
- ctx.font = "16px sans-serif";
49
- ctx.textAlign = "center";
50
- ctx.textBaseline = "middle";
51
- ctx.fillText("Rotated", width / 2, height / 2);
49
+ canvas.fillStyle = "#000000";
50
+ canvas.font = "16px sans-serif";
51
+ canvas.textAlign = "center";
52
+ canvas.textBaseline = "middle";
53
+ canvas.fillText("Rotated", width / 2, height / 2);
52
54
  },
53
55
  });
54
56
 
@@ -57,24 +59,25 @@ const CircleProgress = CustomDraw({
57
59
  width: 140,
58
60
  height: 140,
59
61
  draw(ctx, { width, height, inner }) {
62
+ const canvas = ctx.canvas;
60
63
  const centerX = width / 2;
61
64
  const centerY = height / 2;
62
65
  const radius = Math.min(width, height) / 2 - 8;
63
66
 
64
67
  // 绘制背景圆
65
- ctx.strokeStyle = "rgba(0, 0, 0, 0.1)";
66
- ctx.lineWidth = 8;
67
- ctx.beginPath();
68
- ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);
69
- ctx.stroke();
68
+ canvas.strokeStyle = "rgba(0, 0, 0, 0.1)";
69
+ canvas.lineWidth = 8;
70
+ canvas.beginPath();
71
+ canvas.arc(centerX, centerY, radius, 0, Math.PI * 2);
72
+ canvas.stroke();
70
73
 
71
74
  // 绘制进度圆(65% 完成)
72
75
  const percentage = 65;
73
- ctx.strokeStyle = "#ff6b6b";
74
- ctx.lineCap = "round";
75
- ctx.beginPath();
76
- ctx.arc(centerX, centerY, radius, -Math.PI / 2, -Math.PI / 2 + (percentage / 100) * Math.PI * 2);
77
- ctx.stroke();
76
+ canvas.strokeStyle = "#ff6b6b";
77
+ canvas.lineCap = "round";
78
+ canvas.beginPath();
79
+ canvas.arc(centerX, centerY, radius, -Math.PI / 2, -Math.PI / 2 + (percentage / 100) * Math.PI * 2);
80
+ canvas.stroke();
78
81
 
79
82
  // 调用 inner() 在中央渲染子元素(百分比文本)
80
83
  inner?.();
@@ -99,14 +102,15 @@ const StarShape = CustomDraw({
99
102
  width: 150,
100
103
  height: 150,
101
104
  draw(ctx, { width, height }) {
105
+ const canvas = ctx.canvas;
102
106
  const centerX = width / 2;
103
107
  const centerY = height / 2;
104
108
  const points = 5;
105
109
  const outerRadius = Math.min(width, height) / 2 - 5;
106
110
  const innerRadius = outerRadius * 0.4;
107
111
 
108
- ctx.fillStyle = "#ffd93d";
109
- ctx.beginPath();
112
+ canvas.fillStyle = "#ffd93d";
113
+ canvas.beginPath();
110
114
 
111
115
  for (let i = 0; i < points * 2; i++) {
112
116
  const radius = i % 2 === 0 ? outerRadius : innerRadius;
@@ -115,19 +119,19 @@ const StarShape = CustomDraw({
115
119
  const y = centerY + radius * Math.sin(angle);
116
120
 
117
121
  if (i === 0) {
118
- ctx.moveTo(x, y);
122
+ canvas.moveTo(x, y);
119
123
  } else {
120
- ctx.lineTo(x, y);
124
+ canvas.lineTo(x, y);
121
125
  }
122
126
  }
123
127
 
124
- ctx.closePath();
125
- ctx.fill();
128
+ canvas.closePath();
129
+ canvas.fill();
126
130
 
127
131
  // 描边
128
- ctx.strokeStyle = "#fa8c16";
129
- ctx.lineWidth = 2;
130
- ctx.stroke();
132
+ canvas.strokeStyle = "#fa8c16";
133
+ canvas.lineWidth = 2;
134
+ canvas.stroke();
131
135
  },
132
136
  });
133
137
 
@@ -246,7 +250,7 @@ const layout = canvas.render(
246
250
  }),
247
251
  Text({
248
252
  content:
249
- "CustomDraw 支持直接调用 Canvas API。内部的 save/restore 会自动平衡,transform 也会自动相对处理。使用 inner() 方法可以在自定义绘制中渲染子元素。",
253
+ "CustomDraw 提供受控的 transform/save/restore 能力,并通过 ctx.canvas 暴露原生 Canvas API。使用 inner() 方法可以在自定义绘制中渲染子元素。",
250
254
  font: { size: 12, family: "unifont" },
251
255
  color: "#1890ff",
252
256
  wrap: true,
@@ -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
  }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codehz/draw-call",
3
- "version": "0.5.3",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "main": "./dist/node/index.cjs",
6
6
  "module": "./dist/node/index.mjs",