@antv/gpt-vis 1.0.0-beta.2 → 1.0.1
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 +282 -43
- package/README.zh-CN.md +286 -47
- package/dist/cjs/gpt-vis/index.js +1 -1
- package/dist/cjs/types/index.d.ts +2 -1
- package/dist/cjs/util/animation.d.ts +2 -0
- package/dist/cjs/util/animation.js +38 -0
- package/dist/cjs/util/components.d.ts +15 -0
- package/dist/cjs/util/components.js +94 -0
- package/dist/cjs/util/crosshair-axis-labels.d.ts +9 -0
- package/dist/cjs/util/crosshair-axis-labels.js +304 -0
- package/dist/cjs/util/index.d.ts +6 -0
- package/dist/cjs/util/index.js +33 -0
- package/dist/cjs/util/interaction.d.ts +14 -0
- package/dist/cjs/util/interaction.js +89 -0
- package/dist/cjs/util/theme.d.ts +18 -24
- package/dist/cjs/util/theme.js +303 -120
- package/dist/cjs/util/tokens.d.ts +31 -0
- package/dist/cjs/util/tokens.js +98 -0
- package/dist/cjs/vis/area/index.d.ts +2 -2
- package/dist/cjs/vis/area/index.js +76 -31
- package/dist/cjs/vis/bar/index.d.ts +2 -2
- package/dist/cjs/vis/bar/index.js +22 -19
- package/dist/cjs/vis/boxplot/index.js +1 -4
- package/dist/cjs/vis/column/index.d.ts +2 -2
- package/dist/cjs/vis/column/index.js +28 -18
- package/dist/cjs/vis/dual-axes/index.d.ts +2 -2
- package/dist/cjs/vis/dual-axes/index.js +90 -36
- package/dist/cjs/vis/fishbone-diagram/index.js +12 -4
- package/dist/cjs/vis/flow-diagram/index.js +27 -11
- package/dist/cjs/vis/funnel/index.d.ts +4 -2
- package/dist/cjs/vis/funnel/index.js +171 -92
- package/dist/cjs/vis/histogram/index.js +1 -4
- package/dist/cjs/vis/indented-tree/index.js +13 -3
- package/dist/cjs/vis/line/index.d.ts +2 -2
- package/dist/cjs/vis/line/index.js +71 -31
- package/dist/cjs/vis/liquid/index.d.ts +2 -2
- package/dist/cjs/vis/liquid/index.js +41 -16
- package/dist/cjs/vis/mindmap/index.js +12 -4
- package/dist/cjs/vis/network-graph/index.js +11 -2
- package/dist/cjs/vis/organization-chart/index.js +12 -3
- package/dist/cjs/vis/pie/index.d.ts +2 -2
- package/dist/cjs/vis/pie/index.js +26 -16
- package/dist/cjs/vis/radar/index.d.ts +2 -2
- package/dist/cjs/vis/radar/index.js +21 -29
- package/dist/cjs/vis/sankey/index.js +1 -4
- package/dist/cjs/vis/scatter/index.d.ts +4 -2
- package/dist/cjs/vis/scatter/index.js +43 -16
- package/dist/cjs/vis/treemap/index.js +1 -4
- package/dist/cjs/vis/venn/index.js +1 -4
- package/dist/cjs/vis/violin/index.js +1 -1
- package/dist/cjs/vis/waterfall/index.js +2 -2
- package/dist/cjs/vis/word-cloud/index.d.ts +3 -2
- package/dist/cjs/vis/word-cloud/index.js +125 -10
- package/dist/esm/gpt-vis/index.js +1 -1
- package/dist/esm/types/index.d.ts +2 -1
- package/dist/esm/util/animation.d.ts +2 -0
- package/dist/esm/util/animation.js +17 -0
- package/dist/esm/util/components.d.ts +15 -0
- package/dist/esm/util/components.js +67 -0
- package/dist/esm/util/crosshair-axis-labels.d.ts +9 -0
- package/dist/esm/util/crosshair-axis-labels.js +328 -0
- package/dist/esm/util/index.d.ts +6 -0
- package/dist/esm/util/index.js +6 -0
- package/dist/esm/util/interaction.d.ts +14 -0
- package/dist/esm/util/interaction.js +73 -0
- package/dist/esm/util/theme.d.ts +18 -24
- package/dist/esm/util/theme.js +302 -126
- package/dist/esm/util/tokens.d.ts +31 -0
- package/dist/esm/util/tokens.js +64 -0
- package/dist/esm/vis/area/index.d.ts +2 -2
- package/dist/esm/vis/area/index.js +91 -41
- package/dist/esm/vis/bar/index.d.ts +2 -2
- package/dist/esm/vis/bar/index.js +28 -29
- package/dist/esm/vis/boxplot/index.js +4 -5
- package/dist/esm/vis/column/index.d.ts +2 -2
- package/dist/esm/vis/column/index.js +36 -29
- package/dist/esm/vis/dual-axes/index.d.ts +2 -2
- package/dist/esm/vis/dual-axes/index.js +123 -43
- package/dist/esm/vis/fishbone-diagram/index.js +6 -5
- package/dist/esm/vis/flow-diagram/index.js +17 -10
- package/dist/esm/vis/funnel/index.d.ts +4 -2
- package/dist/esm/vis/funnel/index.js +156 -83
- package/dist/esm/vis/histogram/index.js +4 -5
- package/dist/esm/vis/indented-tree/index.js +9 -4
- package/dist/esm/vis/line/index.d.ts +2 -2
- package/dist/esm/vis/line/index.js +80 -37
- package/dist/esm/vis/liquid/index.d.ts +2 -2
- package/dist/esm/vis/liquid/index.js +41 -14
- package/dist/esm/vis/mindmap/index.js +6 -5
- package/dist/esm/vis/network-graph/index.js +5 -3
- package/dist/esm/vis/organization-chart/index.js +6 -4
- package/dist/esm/vis/pie/index.d.ts +2 -2
- package/dist/esm/vis/pie/index.js +36 -16
- package/dist/esm/vis/radar/index.d.ts +2 -2
- package/dist/esm/vis/radar/index.js +21 -34
- package/dist/esm/vis/sankey/index.js +4 -5
- package/dist/esm/vis/scatter/index.d.ts +4 -2
- package/dist/esm/vis/scatter/index.js +45 -19
- package/dist/esm/vis/treemap/index.js +4 -5
- package/dist/esm/vis/venn/index.js +4 -5
- package/dist/esm/vis/violin/index.js +5 -13
- package/dist/esm/vis/waterfall/index.js +11 -11
- package/dist/esm/vis/word-cloud/index.d.ts +3 -2
- package/dist/esm/vis/word-cloud/index.js +158 -10
- package/dist/umd/index.min.js +1 -1
- package/package.json +18 -19
package/README.zh-CN.md
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
1
|
<img src="https://gw.alipayobjects.com/zos/antfincdn/R8sN%24GNdh6/language.svg" width="18"> [English](./README.md) | 简体中文
|
|
2
2
|
|
|
3
|
-
<
|
|
3
|
+
<div align="center">
|
|
4
|
+
<img src="https://github.com/eosphoros-ai/GPT-Vis/assets/17919400/c8804ffb-d3d6-45d3-846f-cf217681ab05" height="70" />
|
|
5
|
+
</div>
|
|
6
|
+
|
|
7
|
+
<h1 align="center">GPT-Vis</h1>
|
|
4
8
|
|
|
5
9
|
<div align="center">
|
|
6
|
-
<img src="https://github.com/eosphoros-ai/GPT-Vis/assets/17919400/c8804ffb-d3d6-45d3-846f-cf217681ab05" height="70">
|
|
7
10
|
|
|
8
|
-
面向 LLM 时代的 AI
|
|
11
|
+
面向 LLM 时代的 AI 原生可视化库,框架无关,开箱即用。
|
|
9
12
|
|
|
10
13
|
[](https://www.npmjs.com/package/@antv/gpt-vis)
|
|
11
14
|
[](https://www.npmjs.com/package/@antv/gpt-vis)
|
|
12
15
|
[](./LICENSE)
|
|
13
16
|
|
|
14
17
|
<p align="center">
|
|
15
|
-
<a href="https://gpt-vis.antv.vision" target="_blank">📖 文档</a>
|
|
16
|
-
<a href="/
|
|
17
|
-
<a href="/
|
|
18
|
-
<a href="
|
|
19
|
-
<a href="https://github.com/antvis/mcp-server-chart" target="_blank">🔌 MCP 服务器</a>
|
|
18
|
+
<a href="https://gpt-vis.antv.vision" target="_blank">📖 文档</a> ·
|
|
19
|
+
<a href="https://gpt-vis.antv.vision/examples" target="_blank">🎨 图表示例</a> ·
|
|
20
|
+
<a href="https://github.com/antvis/mcp-server-chart" target="_blank">🔌 MCP 服务</a> ·
|
|
21
|
+
<a href="/skills/chart-visualization" target="_blank">🧩 图表技能</a>
|
|
20
22
|
</p>
|
|
21
23
|
|
|
22
24
|
</div>
|
|
23
25
|
|
|
24
26
|
<div align="center">
|
|
25
|
-
<
|
|
27
|
+
<img src="https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yNtZT47dH1kAAAAAgBAAAAgAemJ7AQ/fmt.webp" width="100%" alt="GPT-Vis Hero Image" />
|
|
26
28
|
</div>
|
|
27
29
|
|
|
28
30
|
<br/>
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
## ✨ 核心特性
|
|
32
|
+
## ✨ 特性
|
|
33
33
|
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
34
|
+
- 🚀 **框架无关** — 原生 JavaScript、React、Vue、Angular,任何框架均可使用
|
|
35
|
+
- ✍️ **类 Markdown 语法** — LLM 可以直接生成的简洁语法,易学易用
|
|
36
|
+
- 🌊 **流式渲染** — 原生支持 AI 模型流式输出,边生成边渲染
|
|
37
|
+
- 🛡️ **高容错** — 优雅处理不完整、格式异常的数据,适配 AI 生成内容的不确定性
|
|
38
|
+
- 📊 **26 种图表** — 统计图表、关系图表、文本可视化,覆盖主流场景
|
|
39
|
+
- 🎨 **主题系统** — 内置亮色、暗色、学术三套主题,支持自定义配色
|
|
40
40
|
|
|
41
41
|
## 🚀 快速开始
|
|
42
42
|
|
|
@@ -57,7 +57,7 @@ const gptVis = new GPTVis({
|
|
|
57
57
|
height: 400,
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
-
//
|
|
60
|
+
// 类 Markdown 的可视化语法
|
|
61
61
|
const visSyntax = `
|
|
62
62
|
vis line
|
|
63
63
|
data
|
|
@@ -72,7 +72,11 @@ data
|
|
|
72
72
|
gptVis.render(visSyntax);
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
###
|
|
75
|
+
### 流式渲染
|
|
76
|
+
|
|
77
|
+
AI 模型边生成、图表边渲染,无需等待完整响应:
|
|
78
|
+
|
|
79
|
+
<img src="https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*_xY7Q6QyuZ4AAAAAWeAAAAgAemJ7AQ/original" width="100%" />
|
|
76
80
|
|
|
77
81
|
```javascript
|
|
78
82
|
import { GPTVis, isVisSyntax } from '@antv/gpt-vis';
|
|
@@ -90,18 +94,20 @@ function onToken(token) {
|
|
|
90
94
|
|
|
91
95
|
## 📚 语法指南
|
|
92
96
|
|
|
93
|
-
|
|
97
|
+
`render()` 支持两种输入格式:vis 语法(适合 LLM 流式生成)和 JSON 对象(适合程序化调用)。
|
|
98
|
+
|
|
99
|
+
### Vis 语法
|
|
100
|
+
|
|
101
|
+
类 Markdown 的声明式语法,LLM 无需学习复杂 API 即可生成:
|
|
94
102
|
|
|
95
103
|
```
|
|
96
104
|
vis [图表类型]
|
|
97
105
|
[属性] [值]
|
|
98
106
|
data
|
|
99
|
-
- [
|
|
107
|
+
- [字段] [值]
|
|
100
108
|
```
|
|
101
109
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
**简单图表:**
|
|
110
|
+
**饼图:**
|
|
105
111
|
|
|
106
112
|
```
|
|
107
113
|
vis pie
|
|
@@ -113,7 +119,29 @@ data
|
|
|
113
119
|
innerRadius 0.6
|
|
114
120
|
```
|
|
115
121
|
|
|
116
|
-
|
|
122
|
+
**主题:**
|
|
123
|
+
|
|
124
|
+
内置三套主题,通过 `theme` 属性切换:
|
|
125
|
+
|
|
126
|
+
| 主题 | 标识 | 背景色 | 色板 |
|
|
127
|
+
| ------------ | --------- | ------ | ----------------------------------------------------- |
|
|
128
|
+
| 默认(亮色) | `default` | `#FFF` | `#1783FF` `#F08F56` `#D580FF` `#00C9C9` `#7863FF` ... |
|
|
129
|
+
| 暗色 | `dark` | `#000` | `#1783FF` `#F08F56` `#D580FF` `#00C9C9` `#7863FF` ... |
|
|
130
|
+
| 学术 | `academy` | `#FFF` | `#4e79a7` `#f28e2c` `#e15759` `#76b7b2` `#59a14f` ... |
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
vis line
|
|
134
|
+
data
|
|
135
|
+
- time 2020
|
|
136
|
+
value 100
|
|
137
|
+
- time 2021
|
|
138
|
+
value 120
|
|
139
|
+
theme dark
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**自定义样式:**
|
|
143
|
+
|
|
144
|
+
通过 `style` 设置线宽、自定义配色等:
|
|
117
145
|
|
|
118
146
|
```
|
|
119
147
|
vis line
|
|
@@ -129,17 +157,89 @@ style
|
|
|
129
157
|
- #5AD8A6
|
|
130
158
|
```
|
|
131
159
|
|
|
132
|
-
|
|
160
|
+
**包含空格的值用引号包裹:**
|
|
133
161
|
|
|
134
162
|
```
|
|
135
|
-
vis
|
|
163
|
+
vis pie
|
|
136
164
|
data
|
|
137
|
-
-
|
|
165
|
+
- category "Q1 销售额"
|
|
166
|
+
value 30
|
|
167
|
+
- category "Q2 销售额"
|
|
168
|
+
value 25
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**层级数据:**
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
vis mindmap
|
|
175
|
+
data
|
|
176
|
+
- name 项目规划
|
|
138
177
|
children
|
|
139
|
-
- name
|
|
140
|
-
- name
|
|
178
|
+
- name 第一阶段
|
|
179
|
+
- name 第二阶段
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### JSON 对象
|
|
183
|
+
|
|
184
|
+
也支持直接传入 JSON 对象,适合程序化调用:
|
|
185
|
+
|
|
186
|
+
```javascript
|
|
187
|
+
gptVis.render({
|
|
188
|
+
type: 'pie',
|
|
189
|
+
data: [
|
|
190
|
+
{ category: 'Android', value: 72 },
|
|
191
|
+
{ category: 'iOS', value: 28 },
|
|
192
|
+
],
|
|
193
|
+
});
|
|
141
194
|
```
|
|
142
195
|
|
|
196
|
+
## 📊 图表类型
|
|
197
|
+
|
|
198
|
+
支持 26 种图表,覆盖统计分析、关系网络、文本可视化三大类。
|
|
199
|
+
|
|
200
|
+
### 统计图表(18 种)
|
|
201
|
+
|
|
202
|
+
| 图表 | 类型标识 |
|
|
203
|
+
| -------- | ------------ |
|
|
204
|
+
| 折线图 | `line` |
|
|
205
|
+
| 面积图 | `area` |
|
|
206
|
+
| 柱状图 | `column` |
|
|
207
|
+
| 条形图 | `bar` |
|
|
208
|
+
| 饼图 | `pie` |
|
|
209
|
+
| 散点图 | `scatter` |
|
|
210
|
+
| 雷达图 | `radar` |
|
|
211
|
+
| 漏斗图 | `funnel` |
|
|
212
|
+
| 瀑布图 | `waterfall` |
|
|
213
|
+
| 双轴图 | `dual-axes` |
|
|
214
|
+
| 直方图 | `histogram` |
|
|
215
|
+
| 箱线图 | `boxplot` |
|
|
216
|
+
| 小提琴图 | `violin` |
|
|
217
|
+
| 韦恩图 | `venn` |
|
|
218
|
+
| 桑基图 | `sankey` |
|
|
219
|
+
| 树图 | `treemap` |
|
|
220
|
+
| 词云 | `word-cloud` |
|
|
221
|
+
| 水波图 | `liquid` |
|
|
222
|
+
|
|
223
|
+
### 关系图表(6 种)
|
|
224
|
+
|
|
225
|
+
| 图表 | 类型标识 |
|
|
226
|
+
| ---------- | -------------------- |
|
|
227
|
+
| 流程图 | `flow-diagram` |
|
|
228
|
+
| 网络图 | `network-graph` |
|
|
229
|
+
| 思维导图 | `mindmap` |
|
|
230
|
+
| 缩进树 | `indented-tree` |
|
|
231
|
+
| 组织架构图 | `organization-chart` |
|
|
232
|
+
| 鱼骨图 | `fishbone-diagram` |
|
|
233
|
+
|
|
234
|
+
### 文本可视化(2 种)
|
|
235
|
+
|
|
236
|
+
| 图表 | 类型标识 |
|
|
237
|
+
| -------- | --------- |
|
|
238
|
+
| 表格 | `table` |
|
|
239
|
+
| 文本摘要 | `summary` |
|
|
240
|
+
|
|
241
|
+
查看全部示例 → [图表示例](https://gpt-vis.antv.vision/examples)
|
|
242
|
+
|
|
143
243
|
## 🔧 框架集成
|
|
144
244
|
|
|
145
245
|
<details>
|
|
@@ -191,25 +291,22 @@ function ChartComponent({ visSyntax }) {
|
|
|
191
291
|
</template>
|
|
192
292
|
|
|
193
293
|
<script setup>
|
|
194
|
-
import { ref,
|
|
294
|
+
import { ref, watch, onUnmounted } from 'vue';
|
|
195
295
|
import { GPTVis } from '@antv/gpt-vis';
|
|
196
296
|
|
|
197
297
|
const props = defineProps(['visSyntax']);
|
|
198
298
|
const chartRef = ref(null);
|
|
199
299
|
let gptVis = null;
|
|
200
300
|
|
|
201
|
-
onMounted(() => {
|
|
202
|
-
gptVis = new GPTVis({ container: chartRef.value, width: 600, height: 400 });
|
|
203
|
-
gptVis.render(props.visSyntax);
|
|
204
|
-
});
|
|
205
|
-
|
|
206
301
|
watch(
|
|
207
302
|
() => props.visSyntax,
|
|
208
|
-
(
|
|
209
|
-
if (gptVis) {
|
|
210
|
-
gptVis.
|
|
303
|
+
(syntax) => {
|
|
304
|
+
if (!gptVis) {
|
|
305
|
+
gptVis = new GPTVis({ container: chartRef.value, width: 600, height: 400 });
|
|
211
306
|
}
|
|
307
|
+
gptVis.render(syntax);
|
|
212
308
|
},
|
|
309
|
+
{ immediate: true },
|
|
213
310
|
);
|
|
214
311
|
|
|
215
312
|
onUnmounted(() => gptVis?.destroy());
|
|
@@ -218,18 +315,160 @@ onUnmounted(() => gptVis?.destroy());
|
|
|
218
315
|
|
|
219
316
|
</details>
|
|
220
317
|
|
|
221
|
-
|
|
318
|
+
<details>
|
|
319
|
+
<summary><strong>Markdown 渲染器(marked)</strong></summary>
|
|
320
|
+
|
|
321
|
+
GPT-Vis 的 vis 语法天然兼容 Markdown code fence,可以与任何 Markdown 渲染器集成。以下示例使用 `marked` + `marked-highlight`,普通代码块走语法高亮,`vis` 代码块自动渲染为交互式图表。
|
|
222
322
|
|
|
223
|
-
|
|
323
|
+
**安装依赖:**
|
|
224
324
|
|
|
225
|
-
|
|
325
|
+
```bash
|
|
326
|
+
npm install @antv/gpt-vis marked marked-highlight highlight.js
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
**完整示例:**
|
|
330
|
+
|
|
331
|
+
```javascript
|
|
332
|
+
import { Marked } from 'marked';
|
|
333
|
+
import { markedHighlight } from 'marked-highlight';
|
|
334
|
+
import hljs from 'highlight.js';
|
|
335
|
+
import { GPTVis } from '@antv/gpt-vis';
|
|
226
336
|
|
|
227
|
-
|
|
337
|
+
class GPTVisElement extends HTMLElement {
|
|
338
|
+
connectedCallback() {
|
|
339
|
+
const syntax = decodeURIComponent(this.dataset.syntax);
|
|
340
|
+
this._instance = new GPTVis({ container: this });
|
|
341
|
+
this._instance.render(syntax);
|
|
342
|
+
}
|
|
343
|
+
disconnectedCallback() {
|
|
344
|
+
this._instance?.destroy();
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
if (!customElements.get('gpt-vis')) {
|
|
348
|
+
customElements.define('gpt-vis', GPTVisElement);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const marked = new Marked(
|
|
352
|
+
markedHighlight({
|
|
353
|
+
langPrefix: 'hljs language-',
|
|
354
|
+
highlight(code, lang) {
|
|
355
|
+
if (lang?.startsWith('vis')) return code;
|
|
356
|
+
const language = hljs.getLanguage(lang) ? lang : 'plaintext';
|
|
357
|
+
return hljs.highlight(code, { language }).value;
|
|
358
|
+
},
|
|
359
|
+
}),
|
|
360
|
+
{
|
|
361
|
+
renderer: {
|
|
362
|
+
code({ text, lang }) {
|
|
363
|
+
if (lang?.startsWith('vis')) {
|
|
364
|
+
const syntax = encodeURIComponent(lang + '\n' + text);
|
|
365
|
+
return `<gpt-vis data-syntax="${syntax}" style="min-height:300px"></gpt-vis>`;
|
|
366
|
+
}
|
|
367
|
+
return false;
|
|
368
|
+
},
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
);
|
|
372
|
+
|
|
373
|
+
const markdown = `# My Report
|
|
374
|
+
|
|
375
|
+
\`\`\`vis bar
|
|
376
|
+
data
|
|
377
|
+
- category Python
|
|
378
|
+
value 28.1
|
|
379
|
+
- category JavaScript
|
|
380
|
+
value 18.5
|
|
381
|
+
- category Java
|
|
382
|
+
value 15.6
|
|
383
|
+
- category "C/C++"
|
|
384
|
+
value 12.3
|
|
385
|
+
title 2024 Programming Language Popularity
|
|
386
|
+
\`\`\`
|
|
387
|
+
`;
|
|
388
|
+
|
|
389
|
+
document.getElementById('content').innerHTML = marked.parse(markdown);
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
</details>
|
|
393
|
+
|
|
394
|
+
## 🧩 Shadcn/ui
|
|
395
|
+
|
|
396
|
+
通过 shadcn CLI 将 GPT-Vis React 组件直接复制到你的项目中 — 完全源代码控制,高度可定制。
|
|
397
|
+
|
|
398
|
+
### 基础组件
|
|
399
|
+
|
|
400
|
+
通用的 `GPTVis` 组件,支持全部 26 种图表类型的 vis 语法字符串或 JSON 配置对象:
|
|
401
|
+
|
|
402
|
+
```bash
|
|
403
|
+
npx shadcn@latest add @gpt-vis/gpt-vis
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
```tsx
|
|
407
|
+
import { GPTVis } from '@/components/ui/gpt-vis';
|
|
408
|
+
|
|
409
|
+
<GPTVis
|
|
410
|
+
content="vis line
|
|
411
|
+
data
|
|
412
|
+
- time 2020
|
|
413
|
+
value 100
|
|
414
|
+
- time 2021
|
|
415
|
+
value 120
|
|
416
|
+
- time 2022
|
|
417
|
+
value 150
|
|
418
|
+
title 销售趋势"
|
|
419
|
+
theme="academy"
|
|
420
|
+
/>;
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### 类型化图表组件
|
|
424
|
+
|
|
425
|
+
每种图表类型都有独立的组件,提供类型安全的 `config` 属性 — 仅支持 JSON,带 TypeScript 类型校验:
|
|
426
|
+
|
|
427
|
+
```bash
|
|
428
|
+
npx shadcn@latest add @gpt-vis/line
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
```tsx
|
|
432
|
+
import { Line } from '@/components/ui/line';
|
|
433
|
+
|
|
434
|
+
<Line
|
|
435
|
+
config={{
|
|
436
|
+
data: [
|
|
437
|
+
{ time: '2020', value: 100 },
|
|
438
|
+
{ time: '2021', value: 120 },
|
|
439
|
+
{ time: '2022', value: 150 },
|
|
440
|
+
],
|
|
441
|
+
title: '销售趋势',
|
|
442
|
+
axisXTitle: '年份',
|
|
443
|
+
}}
|
|
444
|
+
height={400}
|
|
445
|
+
/>;
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
全部 26 种图表类型均可用,按名称安装即可:
|
|
449
|
+
|
|
450
|
+
```bash
|
|
451
|
+
npx shadcn@latest add @gpt-vis/pie
|
|
452
|
+
npx shadcn@latest add @gpt-vis/bar
|
|
453
|
+
npx shadcn@latest add @gpt-vis/mindmap
|
|
454
|
+
# ...等等
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
每个类型化组件自动将基础 `GPTVis` 组件作为依赖安装。`width`、`height`、`theme`、`wrapper`、`locale`、`className`、`containerStyle` 等属性在所有组件中保持一致。
|
|
458
|
+
|
|
459
|
+
## 🤖 AI 生态
|
|
460
|
+
|
|
461
|
+
GPT-Vis 提供完整的 AI 集成方案:
|
|
462
|
+
|
|
463
|
+
- **[MCP 服务](https://github.com/antvis/mcp-server-chart)** — 通过 Model Context Protocol 让 AI 模型直接调用可视化能力
|
|
464
|
+
- **[图表技能](https://github.com/antvis/GPT-Vis/tree/main/skills/chart-visualization)** — 为 AI 助手提供图表推荐与生成能力,支持语法模式和代码模式两种输出
|
|
465
|
+
|
|
466
|
+
## 🤝 贡献
|
|
228
467
|
|
|
229
|
-
|
|
468
|
+
> **AI 生成代码策略**:本项目仅合并 AI 生成的代码。
|
|
230
469
|
|
|
231
|
-
1. 提交 Issue
|
|
232
|
-
2. 标记 @copilot
|
|
470
|
+
1. 提交 Issue 描述问题或需求
|
|
471
|
+
2. 标记 @copilot 生成实现方案
|
|
233
472
|
3. 提交包含 AI 生成代码的 PR
|
|
234
473
|
|
|
235
474
|
## 📄 开源协议
|
|
@@ -118,7 +118,7 @@ var _GPTVis = class {
|
|
|
118
118
|
this.wrapperInstance = (0, import_vis_wrapper.createVisWrapper)(this.options.container, {
|
|
119
119
|
chartType: type,
|
|
120
120
|
syntax: config,
|
|
121
|
-
locale: this.options.locale || "
|
|
121
|
+
locale: this.options.locale || "en-US"
|
|
122
122
|
});
|
|
123
123
|
} else {
|
|
124
124
|
this.wrapperInstance.update(config);
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
* Common visualization options for all chart components.
|
|
3
3
|
* Defines the container and dimensions for rendering visualizations.
|
|
4
4
|
*/
|
|
5
|
+
export type VisualizationTheme = 'default' | 'light' | 'dark' | 'academy';
|
|
5
6
|
export interface VisualizationOptions {
|
|
6
7
|
container: string | HTMLElement;
|
|
7
8
|
width?: number;
|
|
8
9
|
height?: number;
|
|
9
|
-
theme?:
|
|
10
|
+
theme?: VisualizationTheme;
|
|
10
11
|
wrapper?: boolean;
|
|
11
12
|
locale?: string;
|
|
12
13
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// src/util/animation.ts
|
|
20
|
+
var animation_exports = {};
|
|
21
|
+
__export(animation_exports, {
|
|
22
|
+
getChartAnimation: () => getChartAnimation
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(animation_exports);
|
|
25
|
+
var prefersReducedMotion = () => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
26
|
+
var getChartAnimation = (hasRendered, enterType) => {
|
|
27
|
+
if (hasRendered || prefersReducedMotion())
|
|
28
|
+
return false;
|
|
29
|
+
return {
|
|
30
|
+
enter: enterType ? { type: enterType } : {},
|
|
31
|
+
update: { type: null },
|
|
32
|
+
exit: { type: null }
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
36
|
+
0 && (module.exports = {
|
|
37
|
+
getChartAnimation
|
|
38
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type ChartLocale = 'en-US' | 'zh-CN';
|
|
2
|
+
export type CartesianXAxisOptions = {
|
|
3
|
+
xLabels?: unknown[];
|
|
4
|
+
chartWidth?: number;
|
|
5
|
+
};
|
|
6
|
+
export type CartesianAxisOptions = CartesianXAxisOptions & {
|
|
7
|
+
axisXTitle?: string | false;
|
|
8
|
+
axisYTitle?: string | false;
|
|
9
|
+
};
|
|
10
|
+
export declare const resolveChartLocale: (locale?: string) => ChartLocale;
|
|
11
|
+
export declare const getCartesianLayout: ({ xLabels, chartWidth, }: CartesianXAxisOptions) => Record<string, number>;
|
|
12
|
+
export declare const getCartesianAxis: ({ axisXTitle, axisYTitle, xLabels, chartWidth, }: CartesianAxisOptions) => Record<'x' | 'y', Record<string, unknown>>;
|
|
13
|
+
export declare const getColorLegend: (visible: boolean) => false | {
|
|
14
|
+
color: Record<string, never>;
|
|
15
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// src/util/components.ts
|
|
20
|
+
var components_exports = {};
|
|
21
|
+
__export(components_exports, {
|
|
22
|
+
getCartesianAxis: () => getCartesianAxis,
|
|
23
|
+
getCartesianLayout: () => getCartesianLayout,
|
|
24
|
+
getColorLegend: () => getColorLegend,
|
|
25
|
+
resolveChartLocale: () => resolveChartLocale
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(components_exports);
|
|
28
|
+
var DEFAULT_CHART_WIDTH = 640;
|
|
29
|
+
var AXIS_HORIZONTAL_PADDING = 96;
|
|
30
|
+
var ANGLED_LABEL_MARGIN_RIGHT_MIN = 32;
|
|
31
|
+
var ANGLED_LABEL_MARGIN_RIGHT_MAX = 64;
|
|
32
|
+
var ANGLED_LABEL_EDGE_GAP = 8;
|
|
33
|
+
var estimateLabelWidth = (value) => Array.from(String(value ?? "")).reduce(
|
|
34
|
+
(width, character) => width + ((character.codePointAt(0) ?? 0) > 255 ? 12 : 7),
|
|
35
|
+
0
|
|
36
|
+
);
|
|
37
|
+
var shouldUseAngledXAxisLabels = (labels, chartWidth = DEFAULT_CHART_WIDTH) => {
|
|
38
|
+
if (!(labels == null ? void 0 : labels.length))
|
|
39
|
+
return false;
|
|
40
|
+
const uniqueLabels = Array.from(new Set(labels.map((label) => String(label ?? ""))));
|
|
41
|
+
if (uniqueLabels.length <= 1)
|
|
42
|
+
return false;
|
|
43
|
+
const availableWidth = Math.max(chartWidth - AXIS_HORIZONTAL_PADDING, 240);
|
|
44
|
+
const estimatedWidth = uniqueLabels.reduce(
|
|
45
|
+
(total, label) => total + Math.max(28, estimateLabelWidth(label) + 16),
|
|
46
|
+
0
|
|
47
|
+
);
|
|
48
|
+
return estimatedWidth > availableWidth;
|
|
49
|
+
};
|
|
50
|
+
var resolveChartLocale = (locale) => (locale == null ? void 0 : locale.toLowerCase().startsWith("zh")) ? "zh-CN" : "en-US";
|
|
51
|
+
var getCartesianLayout = ({
|
|
52
|
+
xLabels,
|
|
53
|
+
chartWidth
|
|
54
|
+
}) => {
|
|
55
|
+
if (!shouldUseAngledXAxisLabels(xLabels, chartWidth))
|
|
56
|
+
return {};
|
|
57
|
+
const tailLabel = xLabels == null ? void 0 : xLabels[xLabels.length - 1];
|
|
58
|
+
const labelWidth = estimateLabelWidth(tailLabel);
|
|
59
|
+
const projectedHalfWidth = (labelWidth + 12) * Math.SQRT1_2 / 2;
|
|
60
|
+
return {
|
|
61
|
+
marginRight: Math.min(
|
|
62
|
+
ANGLED_LABEL_MARGIN_RIGHT_MAX,
|
|
63
|
+
Math.max(
|
|
64
|
+
ANGLED_LABEL_MARGIN_RIGHT_MIN,
|
|
65
|
+
Math.ceil(projectedHalfWidth + ANGLED_LABEL_EDGE_GAP)
|
|
66
|
+
)
|
|
67
|
+
)
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
var getCartesianAxis = ({
|
|
71
|
+
axisXTitle,
|
|
72
|
+
axisYTitle,
|
|
73
|
+
xLabels,
|
|
74
|
+
chartWidth
|
|
75
|
+
}) => {
|
|
76
|
+
const useAngledXAxisLabels = shouldUseAngledXAxisLabels(xLabels, chartWidth);
|
|
77
|
+
return {
|
|
78
|
+
x: {
|
|
79
|
+
title: axisXTitle || false,
|
|
80
|
+
...useAngledXAxisLabels ? { labelTransform: "rotate(45)", labelAutoRotate: false } : {}
|
|
81
|
+
},
|
|
82
|
+
y: {
|
|
83
|
+
title: axisYTitle || false
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
var getColorLegend = (visible) => visible ? { color: {} } : false;
|
|
88
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
89
|
+
0 && (module.exports = {
|
|
90
|
+
getCartesianAxis,
|
|
91
|
+
getCartesianLayout,
|
|
92
|
+
getColorLegend,
|
|
93
|
+
resolveChartLocale
|
|
94
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Chart } from '@antv/g2';
|
|
2
|
+
import type { VisualizationTheme } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Bridges G2 tooltip crosshairs to axis value tags.
|
|
5
|
+
*
|
|
6
|
+
* G2 does not currently expose axis tags for tooltip crosshairs, so this adapter
|
|
7
|
+
* reads the rule geometry created by G2 5.4 and renders labels with LineCrosshair.
|
|
8
|
+
*/
|
|
9
|
+
export declare const bindCrosshairAxisLabels: (chart: Chart, theme: VisualizationTheme) => (() => void);
|