@lytjs/plugin-chart 5.0.1 → 6.0.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/dist/index.mjs CHANGED
@@ -1 +1,308 @@
1
- var L=["#42b883","#3b82f6","#f59e0b","#ef4444","#8b5cf6","#ec4899","#14b8a6","#f97316","#06b6d4","#84cc16"],p={title:"",width:600,height:400,showGrid:!0,showLegend:!0,showValues:!1,animationDuration:500,padding:{top:40,right:30,bottom:50,left:60},yMax:0,yMin:0};function z(){return typeof window!="undefined"&&window.devicePixelRatio||1}function I(e,l,f=5){let b=e-l;if(b===0)return[l-1,l,l+1];let n=b/(f-1),s=Math.pow(10,Math.floor(Math.log10(n))),t=n/s,g;t<=1?g=s:t<=2?g=2*s:t<=5?g=5*s:g=10*s;let v=[],c=Math.floor(l/g)*g;for(;c<=e+g*.5;)v.push(Math.round(c*1e10)/1e10),c+=g;return v}function H(e){return e>=1e6?(e/1e6).toFixed(1)+"M":e>=1e3?(e/1e3).toFixed(1)+"K":String(Math.round(e*100)/100)}function Y(e,l,f,b){let{width:n,height:s,padding:t,showGrid:g,showLegend:v,showValues:c,title:D}=f,A=n-t.left-t.right,r=s-t.top-t.bottom,M=[];for(let o of l.datasets)M=M.concat(o.data);let B=f.yMax||Math.max(...M,0),V=f.yMin||Math.min(...M,0),C=I(B,V),w=C[0],S=C[C.length-1]-w||1;if(e.clearRect(0,0,n,s),D&&(e.fillStyle="#2c3e50",e.font="bold 16px -apple-system, BlinkMacSystemFont, sans-serif",e.textAlign="center",e.fillText(D,n/2,24)),g){e.strokeStyle="#e5e7eb",e.lineWidth=1,e.fillStyle="#95a5a6",e.font="12px -apple-system, BlinkMacSystemFont, sans-serif",e.textAlign="right";for(let o of C){let h=t.top+r-(o-w)/S*r;e.beginPath(),e.moveTo(t.left,h),e.lineTo(n-t.right,h),e.stroke(),e.fillText(H(o),t.left-8,h+4)}}let k=l.labels.length,i=A/k,a=Math.min(i*.6/l.datasets.length,50),u=(i-a*l.datasets.length)/2;for(let o=0;o<l.datasets.length;o++){let h=l.datasets[o],m=h.color||L[o%L.length];for(let d=0;d<h.data.length;d++){let T=h.data[d]*b,y=t.left+d*i+u+o*a,W=(T-w)/S*r,F=t.top+r-W;e.fillStyle=m,e.beginPath();let R=Math.min(4,a/4),E=Math.max(0,W);E>R*2?(e.moveTo(y,F+R),e.arcTo(y,F,y+R,F,R),e.arcTo(y+a,F,y+a,F+R,R),e.lineTo(y+a,t.top+r),e.lineTo(y,t.top+r)):e.rect(y,F,a,E),e.fill(),c&&b>=1&&(e.fillStyle="#2c3e50",e.font="11px -apple-system, BlinkMacSystemFont, sans-serif",e.textAlign="center",e.fillText(H(h.data[d]),y+a/2,F-6))}}e.fillStyle="#6c757d",e.font="12px -apple-system, BlinkMacSystemFont, sans-serif",e.textAlign="center";for(let o=0;o<l.labels.length;o++){let h=t.left+o*i+i/2;e.fillText(l.labels[o],h,s-t.bottom+20)}if(v&&l.datasets.length>1){let o=t.top-10,h=n/2-l.datasets.length*80/2;for(let m=0;m<l.datasets.length;m++){let d=l.datasets[m],T=d.color||L[m%L.length];e.fillStyle=T,e.fillRect(h,o-8,12,12),e.fillStyle="#2c3e50",e.font="12px -apple-system, BlinkMacSystemFont, sans-serif",e.textAlign="left",e.fillText(d.label,h+16,o+2),h+=e.measureText(d.label).width+36}}}function q(e,l,f,b){let{width:n,height:s,padding:t,showGrid:g,showLegend:v,showValues:c,title:D}=f,A=n-t.left-t.right,r=s-t.top-t.bottom,M=[];for(let i of l.datasets)M=M.concat(i.data);let B=f.yMax||Math.max(...M,0),V=f.yMin||Math.min(...M,0),C=I(B,V),w=C[0],S=C[C.length-1]-w||1;if(e.clearRect(0,0,n,s),D&&(e.fillStyle="#2c3e50",e.font="bold 16px -apple-system, BlinkMacSystemFont, sans-serif",e.textAlign="center",e.fillText(D,n/2,24)),g){e.strokeStyle="#e5e7eb",e.lineWidth=1,e.fillStyle="#95a5a6",e.font="12px -apple-system, BlinkMacSystemFont, sans-serif",e.textAlign="right";for(let i of C){let a=t.top+r-(i-w)/S*r;e.beginPath(),e.moveTo(t.left,a),e.lineTo(n-t.right,a),e.stroke(),e.fillText(H(i),t.left-8,a+4)}}let k=l.labels.length>1?A/(l.labels.length-1):0;for(let i=0;i<l.datasets.length;i++){let a=l.datasets[i],u=a.color||L[i%L.length];e.beginPath(),e.moveTo(t.left,t.top+r);for(let o=0;o<a.data.length;o++){let h=a.data[o]*b,m=t.left+o*k,d=t.top+r-(h-w)/S*r;e.lineTo(m,d)}e.lineTo(t.left+(a.data.length-1)*k,t.top+r),e.closePath(),e.fillStyle=u+"15",e.fill(),e.beginPath(),e.strokeStyle=u,e.lineWidth=2.5,e.lineJoin="round",e.lineCap="round";for(let o=0;o<a.data.length;o++){let h=a.data[o]*b,m=t.left+o*k,d=t.top+r-(h-w)/S*r;o===0?e.moveTo(m,d):e.lineTo(m,d)}e.stroke();for(let o=0;o<a.data.length;o++){let h=a.data[o]*b,m=t.left+o*k,d=t.top+r-(h-w)/S*r;e.beginPath(),e.arc(m,d,4,0,Math.PI*2),e.fillStyle="#fff",e.fill(),e.strokeStyle=u,e.lineWidth=2,e.stroke(),c&&b>=1&&(e.fillStyle="#2c3e50",e.font="11px -apple-system, BlinkMacSystemFont, sans-serif",e.textAlign="center",e.fillText(H(a.data[o]),m,d-10))}}e.fillStyle="#6c757d",e.font="12px -apple-system, BlinkMacSystemFont, sans-serif",e.textAlign="center";for(let i=0;i<l.labels.length;i++){let a=t.left+i*k;e.fillText(l.labels[i],a,s-t.bottom+20)}if(v&&l.datasets.length>1){let i=t.top-10,a=n/2-l.datasets.length*80/2;for(let u=0;u<l.datasets.length;u++){let o=l.datasets[u],h=o.color||L[u%L.length];e.strokeStyle=h,e.lineWidth=2.5,e.beginPath(),e.moveTo(a,i-2),e.lineTo(a+16,i-2),e.stroke(),e.fillStyle="#2c3e50",e.font="12px -apple-system, BlinkMacSystemFont, sans-serif",e.textAlign="left",e.fillText(o.label,a+22,i+2),a+=e.measureText(o.label).width+42}}}function N(e,l){var V,C,w,G,S,k,i,a,u,o,h,m,d;let f;e instanceof HTMLCanvasElement?f=e:(f=document.createElement("canvas"),e.appendChild(f));let b=f.getContext("2d"),n=l.options,s=n==null?void 0:n.padding,t={title:(V=n==null?void 0:n.title)!=null?V:p.title,width:(C=n==null?void 0:n.width)!=null?C:p.width,height:(w=n==null?void 0:n.height)!=null?w:p.height,showGrid:(G=n==null?void 0:n.showGrid)!=null?G:p.showGrid,showLegend:(S=n==null?void 0:n.showLegend)!=null?S:p.showLegend,showValues:(k=n==null?void 0:n.showValues)!=null?k:p.showValues,animationDuration:(i=n==null?void 0:n.animationDuration)!=null?i:p.animationDuration,padding:{top:(a=s==null?void 0:s.top)!=null?a:p.padding.top,right:(u=s==null?void 0:s.right)!=null?u:p.padding.right,bottom:(o=s==null?void 0:s.bottom)!=null?o:p.padding.bottom,left:(h=s==null?void 0:s.left)!=null?h:p.padding.left},yMax:(m=n==null?void 0:n.yMax)!=null?m:p.yMax,yMin:(d=n==null?void 0:n.yMin)!=null?d:p.yMin},g=z(),v=t.width,c=t.height,D=l.data;function A(){f.width=v*g,f.height=c*g,f.style.width=v+"px",f.style.height=c+"px",b.setTransform(g,0,0,g,0,0)}let r=null;function M(T){l.type==="bar"?Y(b,D,t,T):q(b,D,t,T)}function B(){r!==null&&cancelAnimationFrame(r);let T=performance.now(),y=t.animationDuration;function W(F){let R=F-T,E=Math.min(R/y,1),P=1-Math.pow(1-E,3);M(P),E<1?r=requestAnimationFrame(W):r=null}r=requestAnimationFrame(W)}return A(),B(),{update(T){D=T,A(),B()},resize(T,y){v=T,c=y,A(),M(1)},destroy(){r!==null&&(cancelAnimationFrame(r),r=null),b.clearRect(0,0,v,c),f.parentElement&&e instanceof HTMLElement&&f!==e&&e.removeChild(f)},getContext(){return b}}}export{N as createChart};
1
+ import { definePlugin } from '@lytjs/core';
2
+
3
+ // src/index.ts
4
+ var DEFAULT_COLORS = [
5
+ "#1890ff",
6
+ "#52c41a",
7
+ "#faad14",
8
+ "#ff4d4f",
9
+ "#722ed1",
10
+ "#13c2c2",
11
+ "#eb2f96",
12
+ "#fa541c"
13
+ ];
14
+ var DEFAULT_CONFIG = {
15
+ showLegend: true,
16
+ showGrid: true,
17
+ width: 400,
18
+ height: 300,
19
+ animationDuration: 500,
20
+ padding: 40
21
+ };
22
+ function createChart(canvas, config, options = {}) {
23
+ const {
24
+ defaultAnimationDuration = 500
25
+ } = options;
26
+ let currentConfig = { ...DEFAULT_CONFIG, ...config };
27
+ let animationFrame = null;
28
+ function getColor(datasetIndex, dataIndex) {
29
+ const dataset = currentConfig.datasets[datasetIndex];
30
+ const dataPoint = dataset?.data?.[dataIndex];
31
+ if (dataPoint?.color) return dataPoint.color;
32
+ if (dataset?.color) return dataset.color;
33
+ const colorIndex = dataIndex % DEFAULT_COLORS.length;
34
+ return DEFAULT_COLORS[colorIndex] || "#1890ff";
35
+ }
36
+ function drawBarChart(ctx, progress = 1) {
37
+ const { width, height, padding, datasets, showGrid } = currentConfig;
38
+ const ctxWidth = width - padding * 2;
39
+ const ctxHeight = height - padding * 2;
40
+ let maxValue = 0;
41
+ datasets.forEach((dataset) => {
42
+ dataset.data.forEach((point) => {
43
+ if (point.value > maxValue) maxValue = point.value;
44
+ });
45
+ });
46
+ if (showGrid) {
47
+ ctx.strokeStyle = "#e8e8e8";
48
+ ctx.lineWidth = 1;
49
+ for (let i = 0; i <= 5; i++) {
50
+ const y = padding + ctxHeight / 5 * i;
51
+ ctx.beginPath();
52
+ ctx.moveTo(padding, y);
53
+ ctx.lineTo(width - padding, y);
54
+ ctx.stroke();
55
+ ctx.fillStyle = "#666";
56
+ ctx.font = "12px sans-serif";
57
+ ctx.textAlign = "right";
58
+ ctx.fillText(
59
+ Math.round(maxValue - maxValue / 5 * i).toString(),
60
+ padding - 10,
61
+ y + 4
62
+ );
63
+ }
64
+ }
65
+ const totalBars = datasets.reduce((sum, ds) => sum + ds.data.length, 0);
66
+ const barWidth = ctxWidth / totalBars * 0.7;
67
+ const gap = ctxWidth / totalBars * 0.3;
68
+ let x = padding + gap / 2;
69
+ datasets.forEach((dataset, datasetIndex) => {
70
+ dataset.data.forEach((point, dataIndex) => {
71
+ const barHeight = point.value / maxValue * ctxHeight * progress;
72
+ const y = height - padding - barHeight;
73
+ ctx.fillStyle = getColor(datasetIndex, dataIndex);
74
+ ctx.fillRect(x, y, barWidth, barHeight);
75
+ ctx.fillStyle = "#666";
76
+ ctx.font = "11px sans-serif";
77
+ ctx.textAlign = "center";
78
+ ctx.fillText(
79
+ point.label,
80
+ x + barWidth / 2,
81
+ height - padding + 20
82
+ );
83
+ x += barWidth + gap;
84
+ });
85
+ });
86
+ }
87
+ function drawLineChart(ctx, progress = 1) {
88
+ const { width, height, padding, datasets, showGrid } = currentConfig;
89
+ const ctxWidth = width - padding * 2;
90
+ const ctxHeight = height - padding * 2;
91
+ let maxValue = 0;
92
+ datasets.forEach((dataset) => {
93
+ dataset.data.forEach((point) => {
94
+ if (point.value > maxValue) maxValue = point.value;
95
+ });
96
+ });
97
+ if (showGrid) {
98
+ ctx.strokeStyle = "#e8e8e8";
99
+ ctx.lineWidth = 1;
100
+ for (let i = 0; i <= 5; i++) {
101
+ const y = padding + ctxHeight / 5 * i;
102
+ ctx.beginPath();
103
+ ctx.moveTo(padding, y);
104
+ ctx.lineTo(width - padding, y);
105
+ ctx.stroke();
106
+ ctx.fillStyle = "#666";
107
+ ctx.font = "12px sans-serif";
108
+ ctx.textAlign = "right";
109
+ ctx.fillText(
110
+ Math.round(maxValue - maxValue / 5 * i).toString(),
111
+ padding - 10,
112
+ y + 4
113
+ );
114
+ }
115
+ }
116
+ datasets.forEach((dataset, datasetIndex) => {
117
+ const color = getColor(datasetIndex, 0);
118
+ ctx.strokeStyle = color;
119
+ ctx.fillStyle = color;
120
+ ctx.lineWidth = dataset.borderWidth || 2;
121
+ ctx.beginPath();
122
+ const stepX = ctxWidth / (dataset.data.length - 1);
123
+ dataset.data.forEach((point, index) => {
124
+ const x = padding + stepX * index;
125
+ const y = height - padding - point.value / maxValue * ctxHeight * progress;
126
+ if (index === 0) {
127
+ ctx.moveTo(x, y);
128
+ } else {
129
+ ctx.lineTo(x, y);
130
+ }
131
+ ctx.beginPath();
132
+ ctx.arc(x, y, 4, 0, Math.PI * 2);
133
+ ctx.fill();
134
+ ctx.beginPath();
135
+ ctx.moveTo(x, y);
136
+ ctx.fillStyle = "#666";
137
+ ctx.font = "11px sans-serif";
138
+ ctx.textAlign = "center";
139
+ ctx.fillText(
140
+ point.label,
141
+ x,
142
+ height - padding + 20
143
+ );
144
+ });
145
+ ctx.stroke();
146
+ });
147
+ }
148
+ function drawPieChart(ctx, progress = 1) {
149
+ const { width, height, padding, datasets } = currentConfig;
150
+ const centerX = width / 2;
151
+ const centerY = height / 2;
152
+ const radius = Math.min(width, height) / 2 - padding;
153
+ let totalValue = 0;
154
+ datasets.forEach((dataset) => {
155
+ dataset.data.forEach((point) => {
156
+ totalValue += point.value;
157
+ });
158
+ });
159
+ let currentAngle = -Math.PI / 2;
160
+ datasets.forEach((dataset, datasetIndex) => {
161
+ dataset.data.forEach((point, dataIndex) => {
162
+ const sliceAngle = point.value / totalValue * Math.PI * 2 * progress;
163
+ ctx.fillStyle = getColor(datasetIndex, dataIndex);
164
+ ctx.beginPath();
165
+ ctx.moveTo(centerX, centerY);
166
+ ctx.arc(centerX, centerY, radius, currentAngle, currentAngle + sliceAngle);
167
+ ctx.closePath();
168
+ ctx.fill();
169
+ currentAngle += sliceAngle;
170
+ });
171
+ });
172
+ }
173
+ function drawDoughnutChart(ctx, progress = 1) {
174
+ const { width, height, padding, datasets } = currentConfig;
175
+ const centerX = width / 2;
176
+ const centerY = height / 2;
177
+ const outerRadius = Math.min(width, height) / 2 - padding;
178
+ const innerRadius = outerRadius * 0.5;
179
+ let totalValue = 0;
180
+ datasets.forEach((dataset) => {
181
+ dataset.data.forEach((point) => {
182
+ totalValue += point.value;
183
+ });
184
+ });
185
+ let currentAngle = -Math.PI / 2;
186
+ datasets.forEach((dataset, datasetIndex) => {
187
+ dataset.data.forEach((point, dataIndex) => {
188
+ const sliceAngle = point.value / totalValue * Math.PI * 2 * progress;
189
+ ctx.fillStyle = getColor(datasetIndex, dataIndex);
190
+ ctx.beginPath();
191
+ ctx.arc(centerX, centerY, outerRadius, currentAngle, currentAngle + sliceAngle);
192
+ ctx.arc(centerX, centerY, innerRadius, currentAngle + sliceAngle, currentAngle, true);
193
+ ctx.closePath();
194
+ ctx.fill();
195
+ currentAngle += sliceAngle;
196
+ });
197
+ });
198
+ }
199
+ function drawTitle(ctx) {
200
+ if (!currentConfig.title) return;
201
+ ctx.fillStyle = "#333";
202
+ ctx.font = "bold 16px sans-serif";
203
+ ctx.textAlign = "center";
204
+ ctx.fillText(currentConfig.title, currentConfig.width / 2, 25);
205
+ }
206
+ function drawLegend(ctx) {
207
+ if (!currentConfig.showLegend) return;
208
+ let legendX = currentConfig.padding;
209
+ const legendY = currentConfig.height - 20;
210
+ currentConfig.datasets.forEach((dataset, datasetIndex) => {
211
+ dataset.data.forEach((point, dataIndex) => {
212
+ const color = getColor(datasetIndex, dataIndex);
213
+ ctx.fillStyle = color;
214
+ ctx.fillRect(legendX, legendY, 12, 12);
215
+ ctx.fillStyle = "#666";
216
+ ctx.font = "12px sans-serif";
217
+ ctx.textAlign = "left";
218
+ ctx.fillText(point.label, legendX + 18, legendY + 10);
219
+ legendX += 100;
220
+ });
221
+ });
222
+ }
223
+ function render() {
224
+ const ctx = canvas.getContext("2d");
225
+ if (!ctx) return;
226
+ canvas.width = currentConfig.width;
227
+ canvas.height = currentConfig.height;
228
+ ctx.clearRect(0, 0, currentConfig.width, currentConfig.height);
229
+ const startTime = Date.now();
230
+ const duration = currentConfig.animationDuration || defaultAnimationDuration;
231
+ function animate() {
232
+ if (!ctx) return;
233
+ const elapsed = Date.now() - startTime;
234
+ const progress = Math.min(elapsed / duration, 1);
235
+ ctx.clearRect(0, 0, currentConfig.width, currentConfig.height);
236
+ drawTitle(ctx);
237
+ switch (currentConfig.type) {
238
+ case "bar":
239
+ drawBarChart(ctx, progress);
240
+ break;
241
+ case "line":
242
+ drawLineChart(ctx, progress);
243
+ break;
244
+ case "pie":
245
+ drawPieChart(ctx, progress);
246
+ break;
247
+ case "doughnut":
248
+ drawDoughnutChart(ctx, progress);
249
+ break;
250
+ }
251
+ drawLegend(ctx);
252
+ if (progress < 1) {
253
+ animationFrame = requestAnimationFrame(animate);
254
+ }
255
+ }
256
+ animate();
257
+ }
258
+ function updateData(datasets) {
259
+ currentConfig.datasets = datasets;
260
+ render();
261
+ }
262
+ function destroy() {
263
+ if (animationFrame) {
264
+ cancelAnimationFrame(animationFrame);
265
+ }
266
+ }
267
+ render();
268
+ return {
269
+ render,
270
+ updateData,
271
+ destroy,
272
+ getCanvas: () => canvas
273
+ };
274
+ }
275
+ var pluginChart = definePlugin({
276
+ name: "chart",
277
+ version: "6.0.0",
278
+ description: "LytJS official chart plugin for rendering charts using Canvas API",
279
+ author: "LytJS Team",
280
+ keywords: ["lytjs", "chart", "canvas", "visualization"],
281
+ schema: {
282
+ type: "object",
283
+ object: {
284
+ properties: {
285
+ defaultColors: {
286
+ type: "array",
287
+ default: DEFAULT_COLORS
288
+ },
289
+ defaultAnimationDuration: { type: "number", default: 500 },
290
+ responsive: { type: "boolean", default: true }
291
+ }
292
+ }
293
+ },
294
+ install(app, options) {
295
+ const chartOptions = options;
296
+ app.provide("lyt-chart", {
297
+ create: (canvas, config) => createChart(canvas, config, chartOptions)
298
+ });
299
+ app.config.globalProperties.$chart = {
300
+ create: (canvas, config) => createChart(canvas, config, chartOptions)
301
+ };
302
+ }
303
+ });
304
+ var index_default = pluginChart;
305
+
306
+ export { DEFAULT_COLORS, createChart, index_default as default };
307
+ //# sourceMappingURL=index.mjs.map
308
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * @lytjs/plugin-chart\r\n *\r\n * LytJS official chart plugin for rendering charts using Canvas API with zero dependencies.\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\nimport { definePlugin } from '@lytjs/core';\r\nimport type {\r\n ChartDataPoint,\r\n ChartDataset,\r\n ChartType,\r\n ChartConfig,\r\n ChartInstance,\r\n ChartPluginOptions,\r\n} from './types';\r\n\r\n// 默认颜色 palette\r\nconst DEFAULT_COLORS = [\r\n '#1890ff',\r\n '#52c41a',\r\n '#faad14',\r\n '#ff4d4f',\r\n '#722ed1',\r\n '#13c2c2',\r\n '#eb2f96',\r\n '#fa541c',\r\n];\r\n\r\n// 默认配置\r\nconst DEFAULT_CONFIG = {\r\n showLegend: true,\r\n showGrid: true,\r\n width: 400,\r\n height: 300,\r\n animationDuration: 500,\r\n padding: 40,\r\n};\r\n\r\n/**\r\n * 创建图表实例\r\n */\r\nfunction createChart(\r\n canvas: HTMLCanvasElement,\r\n config: ChartConfig,\r\n options: ChartPluginOptions = {}\r\n): ChartInstance {\r\n const {\r\n defaultAnimationDuration = 500,\r\n } = options;\r\n\r\n let currentConfig = { ...DEFAULT_CONFIG, ...config };\r\n let animationFrame: number | null = null;\r\n\r\n // 获取颜色\r\n function getColor(datasetIndex: number, dataIndex: number): string {\r\n const dataset = currentConfig.datasets[datasetIndex];\r\n const dataPoint = dataset?.data?.[dataIndex];\r\n if (dataPoint?.color) return dataPoint.color;\r\n if (dataset?.color) return dataset.color;\r\n const colorIndex = dataIndex % DEFAULT_COLORS.length;\r\n return DEFAULT_COLORS[colorIndex] || '#1890ff';\r\n }\r\n\r\n // 绘制柱状图\r\n function drawBarChart(ctx: CanvasRenderingContext2D, progress: number = 1) {\r\n const { width, height, padding, datasets, showGrid } = currentConfig;\r\n const ctxWidth = width - padding * 2;\r\n const ctxHeight = height - padding * 2;\r\n\r\n // 找到最大值\r\n let maxValue = 0;\r\n datasets.forEach((dataset) => {\r\n dataset.data.forEach((point) => {\r\n if (point.value > maxValue) maxValue = point.value;\r\n });\r\n });\r\n\r\n // 绘制网格线\r\n if (showGrid) {\r\n ctx.strokeStyle = '#e8e8e8';\r\n ctx.lineWidth = 1;\r\n for (let i = 0; i <= 5; i++) {\r\n const y = padding + (ctxHeight / 5) * i;\r\n ctx.beginPath();\r\n ctx.moveTo(padding, y);\r\n ctx.lineTo(width - padding, y);\r\n ctx.stroke();\r\n\r\n // Y轴标签\r\n ctx.fillStyle = '#666';\r\n ctx.font = '12px sans-serif';\r\n ctx.textAlign = 'right';\r\n ctx.fillText(\r\n Math.round((maxValue - (maxValue / 5) * i)).toString(),\r\n padding - 10,\r\n y + 4\r\n );\r\n }\r\n }\r\n\r\n // 绘制柱状图\r\n const totalBars = datasets.reduce((sum, ds) => sum + ds.data.length, 0);\r\n const barWidth = ctxWidth / totalBars * 0.7;\r\n const gap = ctxWidth / totalBars * 0.3;\r\n\r\n let x = padding + gap / 2;\r\n\r\n datasets.forEach((dataset, datasetIndex) => {\r\n dataset.data.forEach((point, dataIndex) => {\r\n const barHeight = (point.value / maxValue) * ctxHeight * progress;\r\n const y = height - padding - barHeight;\r\n\r\n ctx.fillStyle = getColor(datasetIndex, dataIndex);\r\n ctx.fillRect(x, y, barWidth, barHeight);\r\n\r\n // X轴标签\r\n ctx.fillStyle = '#666';\r\n ctx.font = '11px sans-serif';\r\n ctx.textAlign = 'center';\r\n ctx.fillText(\r\n point.label,\r\n x + barWidth / 2,\r\n height - padding + 20\r\n );\r\n\r\n x += barWidth + gap;\r\n });\r\n });\r\n }\r\n\r\n // 绘制折线图\r\n function drawLineChart(ctx: CanvasRenderingContext2D, progress: number = 1) {\r\n const { width, height, padding, datasets, showGrid } = currentConfig;\r\n const ctxWidth = width - padding * 2;\r\n const ctxHeight = height - padding * 2;\r\n\r\n // 找到最大值\r\n let maxValue = 0;\r\n datasets.forEach((dataset) => {\r\n dataset.data.forEach((point) => {\r\n if (point.value > maxValue) maxValue = point.value;\r\n });\r\n });\r\n\r\n // 绘制网格线\r\n if (showGrid) {\r\n ctx.strokeStyle = '#e8e8e8';\r\n ctx.lineWidth = 1;\r\n for (let i = 0; i <= 5; i++) {\r\n const y = padding + (ctxHeight / 5) * i;\r\n ctx.beginPath();\r\n ctx.moveTo(padding, y);\r\n ctx.lineTo(width - padding, y);\r\n ctx.stroke();\r\n\r\n // Y轴标签\r\n ctx.fillStyle = '#666';\r\n ctx.font = '12px sans-serif';\r\n ctx.textAlign = 'right';\r\n ctx.fillText(\r\n Math.round((maxValue - (maxValue / 5) * i)).toString(),\r\n padding - 10,\r\n y + 4\r\n );\r\n }\r\n }\r\n\r\n // 绘制折线\r\n datasets.forEach((dataset, datasetIndex) => {\r\n const color = getColor(datasetIndex, 0);\r\n ctx.strokeStyle = color;\r\n ctx.fillStyle = color;\r\n ctx.lineWidth = dataset.borderWidth || 2;\r\n ctx.beginPath();\r\n\r\n const stepX = ctxWidth / (dataset.data.length - 1);\r\n\r\n dataset.data.forEach((point, index) => {\r\n const x = padding + stepX * index;\r\n const y = height - padding - (point.value / maxValue) * ctxHeight * progress;\r\n\r\n if (index === 0) {\r\n ctx.moveTo(x, y);\r\n } else {\r\n ctx.lineTo(x, y);\r\n }\r\n\r\n // 绘制点\r\n ctx.beginPath();\r\n ctx.arc(x, y, 4, 0, Math.PI * 2);\r\n ctx.fill();\r\n ctx.beginPath();\r\n ctx.moveTo(x, y);\r\n\r\n // X轴标签\r\n ctx.fillStyle = '#666';\r\n ctx.font = '11px sans-serif';\r\n ctx.textAlign = 'center';\r\n ctx.fillText(\r\n point.label,\r\n x,\r\n height - padding + 20\r\n );\r\n });\r\n\r\n ctx.stroke();\r\n });\r\n }\r\n\r\n // 绘制饼图\r\n function drawPieChart(ctx: CanvasRenderingContext2D, progress: number = 1) {\r\n const { width, height, padding, datasets } = currentConfig;\r\n const centerX = width / 2;\r\n const centerY = height / 2;\r\n const radius = Math.min(width, height) / 2 - padding;\r\n\r\n // 计算总值\r\n let totalValue = 0;\r\n datasets.forEach((dataset) => {\r\n dataset.data.forEach((point) => {\r\n totalValue += point.value;\r\n });\r\n });\r\n\r\n let currentAngle = -Math.PI / 2; // 从顶部开始\r\n\r\n datasets.forEach((dataset, datasetIndex) => {\r\n dataset.data.forEach((point, dataIndex) => {\r\n const sliceAngle = (point.value / totalValue) * Math.PI * 2 * progress;\r\n\r\n ctx.fillStyle = getColor(datasetIndex, dataIndex);\r\n ctx.beginPath();\r\n ctx.moveTo(centerX, centerY);\r\n ctx.arc(centerX, centerY, radius, currentAngle, currentAngle + sliceAngle);\r\n ctx.closePath();\r\n ctx.fill();\r\n\r\n currentAngle += sliceAngle;\r\n });\r\n });\r\n }\r\n\r\n // 绘制环形图\r\n function drawDoughnutChart(ctx: CanvasRenderingContext2D, progress: number = 1) {\r\n const { width, height, padding, datasets } = currentConfig;\r\n const centerX = width / 2;\r\n const centerY = height / 2;\r\n const outerRadius = Math.min(width, height) / 2 - padding;\r\n const innerRadius = outerRadius * 0.5;\r\n\r\n // 计算总值\r\n let totalValue = 0;\r\n datasets.forEach((dataset) => {\r\n dataset.data.forEach((point) => {\r\n totalValue += point.value;\r\n });\r\n });\r\n\r\n let currentAngle = -Math.PI / 2;\r\n\r\n datasets.forEach((dataset, datasetIndex) => {\r\n dataset.data.forEach((point, dataIndex) => {\r\n const sliceAngle = (point.value / totalValue) * Math.PI * 2 * progress;\r\n\r\n ctx.fillStyle = getColor(datasetIndex, dataIndex);\r\n ctx.beginPath();\r\n ctx.arc(centerX, centerY, outerRadius, currentAngle, currentAngle + sliceAngle);\r\n ctx.arc(centerX, centerY, innerRadius, currentAngle + sliceAngle, currentAngle, true);\r\n ctx.closePath();\r\n ctx.fill();\r\n\r\n currentAngle += sliceAngle;\r\n });\r\n });\r\n }\r\n\r\n // 绘制标题\r\n function drawTitle(ctx: CanvasRenderingContext2D) {\r\n if (!currentConfig.title) return;\r\n\r\n ctx.fillStyle = '#333';\r\n ctx.font = 'bold 16px sans-serif';\r\n ctx.textAlign = 'center';\r\n ctx.fillText(currentConfig.title, currentConfig.width / 2, 25);\r\n }\r\n\r\n // 绘制图例\r\n function drawLegend(ctx: CanvasRenderingContext2D) {\r\n if (!currentConfig.showLegend) return;\r\n\r\n let legendX = currentConfig.padding;\r\n const legendY = currentConfig.height - 20;\r\n let itemIndex = 0;\r\n\r\n currentConfig.datasets.forEach((dataset, datasetIndex) => {\r\n dataset.data.forEach((point, dataIndex) => {\r\n const color = getColor(datasetIndex, dataIndex);\r\n\r\n // 绘制颜色方块\r\n ctx.fillStyle = color;\r\n ctx.fillRect(legendX, legendY, 12, 12);\r\n\r\n // 绘制标签\r\n ctx.fillStyle = '#666';\r\n ctx.font = '12px sans-serif';\r\n ctx.textAlign = 'left';\r\n ctx.fillText(point.label, legendX + 18, legendY + 10);\r\n\r\n legendX += 100;\r\n itemIndex++;\r\n });\r\n });\r\n }\r\n\r\n // 渲染函数\r\n function render() {\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return;\r\n\r\n // 设置 canvas 尺寸\r\n canvas.width = currentConfig.width;\r\n canvas.height = currentConfig.height;\r\n\r\n // 清空画布\r\n ctx.clearRect(0, 0, currentConfig.width, currentConfig.height);\r\n\r\n const startTime = Date.now();\r\n const duration = currentConfig.animationDuration || defaultAnimationDuration;\r\n\r\n function animate() {\r\n if (!ctx) return;\r\n \r\n const elapsed = Date.now() - startTime;\r\n const progress = Math.min(elapsed / duration, 1);\r\n\r\n ctx.clearRect(0, 0, currentConfig.width, currentConfig.height);\r\n\r\n // 绘制标题\r\n drawTitle(ctx);\r\n\r\n // 绘制图表\r\n switch (currentConfig.type) {\r\n case 'bar':\r\n drawBarChart(ctx, progress);\r\n break;\r\n case 'line':\r\n drawLineChart(ctx, progress);\r\n break;\r\n case 'pie':\r\n drawPieChart(ctx, progress);\r\n break;\r\n case 'doughnut':\r\n drawDoughnutChart(ctx, progress);\r\n break;\r\n }\r\n\r\n // 绘制图例\r\n drawLegend(ctx);\r\n\r\n if (progress < 1) {\r\n animationFrame = requestAnimationFrame(animate);\r\n }\r\n }\r\n\r\n animate();\r\n }\r\n\r\n // 更新数据\r\n function updateData(datasets: ChartDataset[]) {\r\n currentConfig.datasets = datasets;\r\n render();\r\n }\r\n\r\n // 销毁\r\n function destroy() {\r\n if (animationFrame) {\r\n cancelAnimationFrame(animationFrame);\r\n }\r\n }\r\n\r\n // 初始化渲染\r\n render();\r\n\r\n return {\r\n render,\r\n updateData,\r\n destroy,\r\n getCanvas: () => canvas,\r\n };\r\n}\r\n\r\nconst pluginChart = definePlugin({\r\n name: 'chart',\r\n version: '6.0.0',\r\n description: 'LytJS official chart plugin for rendering charts using Canvas API',\r\n author: 'LytJS Team',\r\n keywords: ['lytjs', 'chart', 'canvas', 'visualization'],\r\n schema: {\r\n type: 'object',\r\n object: {\r\n properties: {\r\n defaultColors: { \r\n type: 'array', \r\n default: DEFAULT_COLORS,\r\n },\r\n defaultAnimationDuration: { type: 'number', default: 500 },\r\n responsive: { type: 'boolean', default: true },\r\n },\r\n },\r\n },\r\n install(app, options) {\r\n const chartOptions = options as ChartPluginOptions;\r\n\r\n // 提供创建图表的方法\r\n app.provide('lyt-chart', {\r\n create: (canvas: HTMLCanvasElement, config: ChartConfig) =>\r\n createChart(canvas, config, chartOptions),\r\n });\r\n\r\n // 挂载到全局属性\r\n app.config.globalProperties.$chart = {\r\n create: (canvas: HTMLCanvasElement, config: ChartConfig) =>\r\n createChart(canvas, config, chartOptions),\r\n };\r\n },\r\n});\r\n\r\nexport default pluginChart;\r\nexport type {\r\n ChartDataPoint,\r\n ChartDataset,\r\n ChartType,\r\n ChartConfig,\r\n ChartInstance,\r\n ChartPluginOptions,\r\n};\r\nexport { createChart, DEFAULT_COLORS };\r\n"]}
package/package.json CHANGED
@@ -1,45 +1,51 @@
1
1
  {
2
2
  "name": "@lytjs/plugin-chart",
3
- "version": "5.0.1",
4
- "description": "Lyt.js 图表插件 - 提供柱状图和折线图组件,使用 Canvas API 绘制,零运行时依赖",
5
- "main": "dist/index.mjs",
6
- "module": "dist/index.mjs",
7
- "types": "dist/types/index.d.ts",
3
+ "version": "6.0.0",
4
+ "description": "LytJS official chart plugin for rendering charts using Canvas API with zero dependencies",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.mjs",
8
+ "types": "./dist/index.d.ts",
8
9
  "exports": {
9
10
  ".": {
10
- "types": "./dist/types/index.d.ts",
11
+ "types": "./dist/index.d.ts",
11
12
  "import": "./dist/index.mjs",
12
- "require": "./dist/index.cjs",
13
- "default": "./dist/index.mjs"
14
- }
13
+ "require": "./dist/index.cjs"
14
+ },
15
+ "./package.json": "./package.json"
15
16
  },
16
- "sideEffects": false,
17
17
  "files": [
18
18
  "dist"
19
19
  ],
20
+ "sideEffects": false,
21
+ "scripts": {
22
+ "build": "tsup",
23
+ "dev": "tsup --watch",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest",
26
+ "test:coverage": "vitest run --coverage",
27
+ "type-check": "tsc --noEmit",
28
+ "lint": "eslint \"src/**/*.ts\"",
29
+ "clean": "rm -rf dist"
30
+ },
31
+ "dependencies": {
32
+ "@lytjs/core": "^6.0.0"
33
+ },
34
+ "devDependencies": {
35
+ "tsup": "^8.0.0",
36
+ "typescript": "^5.4.0",
37
+ "vitest": "^3.0.0"
38
+ },
20
39
  "license": "MIT",
21
- "author": "lytjs",
22
40
  "repository": {
23
41
  "type": "git",
24
- "url": "https://gitee.com/lytjs/lytjs"
42
+ "url": "https://gitee.com/lytjs/lytjs.git",
43
+ "directory": "packages/plugins/packages/plugin-chart"
25
44
  },
26
- "homepage": "https://gitee.com/lytjs",
27
45
  "keywords": [
28
- "lyt",
29
46
  "lytjs",
30
47
  "chart",
31
- "图表",
32
- "bar",
33
- "line",
34
48
  "canvas",
35
- "可视化",
36
- "visualization",
37
- "zero-dependency"
38
- ],
39
- "engines": {
40
- "node": ">=18.0.0"
41
- },
42
- "publishConfig": {
43
- "access": "public"
44
- }
49
+ "visualization"
50
+ ]
45
51
  }
package/README.md DELETED
@@ -1,113 +0,0 @@
1
- # @lytjs/plugin-chart
2
-
3
- Lyt.js 图表插件 - 提供柱状图和折线图组件,使用 Canvas API 绘制,零运行时依赖。
4
-
5
- ## 特性
6
-
7
- - 柱状图(Bar Chart)和折线图(Line Chart)
8
- - Canvas API 绘制,零运行时依赖
9
- - 高清屏(Retina)适配
10
- - 入场动画(easeOutCubic)
11
- - 多数据系列支持
12
- - 自定义颜色、标题、图例
13
- - Y 轴自动刻度计算
14
- - 数值标签显示
15
- - 响应式尺寸调整
16
-
17
- ## 安装
18
-
19
- ```bash
20
- npm install @lytjs/plugin-chart
21
- ```
22
-
23
- ## 使用
24
-
25
- ### 柱状图
26
-
27
- ```js
28
- import { createChart } from '@lytjs/plugin-chart'
29
-
30
- const chart = createChart(document.getElementById('chart'), {
31
- type: 'bar',
32
- data: {
33
- labels: ['一月', '二月', '三月', '四月', '五月'],
34
- datasets: [
35
- {
36
- label: '销售额',
37
- data: [120, 200, 150, 80, 170],
38
- color: '#42b883',
39
- },
40
- ],
41
- },
42
- options: {
43
- title: '月度销售统计',
44
- width: 600,
45
- height: 400,
46
- showValues: true,
47
- },
48
- })
49
- ```
50
-
51
- ### 折线图
52
-
53
- ```js
54
- const chart = createChart(document.getElementById('chart'), {
55
- type: 'line',
56
- data: {
57
- labels: ['Q1', 'Q2', 'Q3', 'Q4'],
58
- datasets: [
59
- { label: '2024', data: [30, 50, 80, 60], color: '#42b883' },
60
- { label: '2023', data: [20, 40, 60, 50], color: '#3b82f6' },
61
- ],
62
- },
63
- options: {
64
- title: '季度对比',
65
- showLegend: true,
66
- },
67
- })
68
- ```
69
-
70
- ### 更新数据
71
-
72
- ```js
73
- chart.update({
74
- labels: ['A', 'B', 'C'],
75
- datasets: [{ label: '新数据', data: [10, 20, 30] }],
76
- })
77
- ```
78
-
79
- ### 调整尺寸
80
-
81
- ```js
82
- chart.resize(800, 500)
83
- ```
84
-
85
- ### 销毁图表
86
-
87
- ```js
88
- chart.destroy()
89
- ```
90
-
91
- ## API
92
-
93
- ### `createChart(container, config): ChartInstance`
94
-
95
- | 参数 | 类型 | 说明 |
96
- |------|------|------|
97
- | `container` | `HTMLElement \| HTMLCanvasElement` | 容器元素或 Canvas 元素 |
98
- | `config.type` | `'bar' \| 'line'` | 图表类型 |
99
- | `config.data` | `ChartData` | 图表数据 |
100
- | `config.options` | `ChartOptions` | 图表选项(可选) |
101
-
102
- ### ChartInstance
103
-
104
- | 方法 | 说明 |
105
- |------|------|
106
- | `update(data)` | 更新图表数据 |
107
- | `resize(width, height)` | 调整图表尺寸 |
108
- | `destroy()` | 销毁图表 |
109
- | `getContext()` | 获取 Canvas 上下文 |
110
-
111
- ## License
112
-
113
- MIT
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAuBA,WAAW;AACX,KAAK,SAAS,GAAG,KAAK,GAAG,MAAM,CAAC;AAEhC,UAAU;AACV,UAAU,YAAY;IACpB,YAAY;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,YAAY;IACZ,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,YAAY;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,WAAW;AACX,UAAU,SAAS;IACjB,YAAY;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY;IACZ,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,aAAa;AACb,UAAU,YAAY;IACpB,WAAW;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sBAAsB;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,wBAAwB;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,sBAAsB;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU;IACV,OAAO,CAAC,EAAE;QACR,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,aAAa;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAqBD,aAAa;AACb,UAAU,WAAW;IACnB,WAAW;IACX,IAAI,EAAE,SAAS,CAAC;IAChB,WAAW;IACX,IAAI,EAAE,SAAS,CAAC;IAChB,WAAW;IACX,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAED,WAAW;AACX,UAAU,aAAa;IACrB,aAAa;IACb,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;IAC9B,aAAa;IACb,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,gBAAgB;IAChB,OAAO,IAAI,IAAI,CAAC;IAChB,oBAAoB;IACpB,UAAU,IAAI,wBAAwB,CAAC;CACxC;AA2VD;;;;;;GAMG;AACH,iBAAS,WAAW,CAClB,SAAS,EAAE,WAAW,GAAG,iBAAiB,EAC1C,MAAM,EAAE,WAAW,GAClB,aAAa,CAsHf;AAED,OAAO,EAAE,WAAW,EAAE,CAAC;AACvB,YAAY,EACV,SAAS,EACT,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,WAAW,EACX,aAAa,GACd,CAAC"}