10.数据可视化
1. 为什么需要数据可视化?
1.1 数据的价值
数据 = 信息,但原始数据很难理解
生活类比:
- 原始数据:1000个数字(看不懂)
- 可视化:把这些数字变成图表(一眼看懂)
实际例子:
1 | 原始数据: |
1.2 数据可视化的作用
| 作用 | 说明 | 实际案例 |
|---|---|---|
| 直观展示 | 用图表代替数字 | 销售趋势图、用户增长图 |
| 发现规律 | 一眼看出数据规律 | 哪个时间段访问量最高 |
| 辅助决策 | 帮助做出更好的决策 | 根据销售数据调整策略 |
| 提升体验 | 让数据更有趣、更易理解 | 数据看板、统计报表 |
💡 记忆技巧:
数据可视化 = 把"数字"变成"图画",让人一眼就能看懂!
1.3 常见的数据可视化场景
| 场景 | 图表类型 | 示例 |
|---|---|---|
| 趋势分析 | 折线图 | 销售额随时间的变化 |
| 对比分析 | 柱状图 | 不同产品的销量对比 |
| 占比分析 | 饼图 | 不同类别的占比 |
| 分布分析 | 散点图 | 用户年龄分布 |
| 综合展示 | 数据看板 | 多个图表组合展示 |
2. G2Plot图表库:快速上手
2.1 什么是G2Plot?
G2Plot = 基于G2(AntV)的图表库,专为业务场景设计
G2 = 更底层的图形语法库(更灵活,但更复杂)
G2Plot = 基于G2封装的高级图表库(简单易用,适合业务场景)
关系: 1
G2(底层) → G2Plot(高级封装) → Ant Design Vue(UI组件库集成)
优势:
| 优势 | 说明 |
|---|---|
| 简单易用 | API简洁,上手快 |
| 图表丰富 | 支持20+种图表类型 |
| 自动适配 | 自动响应式,适配不同屏幕 |
| 与Ant Design Vue集成 | 完美配合,风格统一 |
2.2 安装G2Plot
安装命令: 1
npm install @antv/g2plot
在Vue中使用: 1
import { Line, Column, Pie } from '@antv/g2plot';
2.3 基础图表:折线图
2.3.1 创建折线图
作用:展示数据随时间的变化趋势
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37<template>
<div id="lineChart" style="width: 600px; height: 300px;"></div>
</template>
<script>
import { Line } from '@antv/g2plot';
import { onMounted } from 'vue';
export default {
setup() {
onMounted(() => {
// 数据
const data = [
{ month: '1月', value: 1000 },
{ month: '2月', value: 1500 },
{ month: '3月', value: 1200 },
{ month: '4月', value: 1800 },
{ month: '5月', value: 2000 }
];
// 创建折线图
const line = new Line('lineChart', {
data,
xField: 'month', // X轴字段
yField: 'value', // Y轴字段
point: {
size: 5,
shape: 'circle'
}
});
// 渲染图表
line.render();
});
}
};
</script>
效果:显示一条折线,展示数据的变化趋势
2.3.2 多条折线图
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16const data = [
{ month: '1月', 销售额: 1000, 利润: 200 },
{ month: '2月', 销售额: 1500, 利润: 300 },
{ month: '3月', 销售额: 1200, 利润: 250 }
];
const line = new Line('lineChart', {
data,
xField: 'month',
yField: ['销售额', '利润'], // 多个Y轴字段
legend: {
position: 'top'
}
});
line.render();
2.4 柱状图
2.4.1 基础柱状图
作用:对比不同类别的数据
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import { Column } from '@antv/g2plot';
const data = [
{ 产品: '产品A', 销量: 100 },
{ 产品: '产品B', 销量: 150 },
{ 产品: '产品C', 销量: 120 }
];
const column = new Column('columnChart', {
data,
xField: '产品',
yField: '销量',
color: '#3498db'
});
column.render();
2.4.2 分组柱状图
作用:对比多个维度的数据
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14const data = [
{ 月份: '1月', 产品A: 100, 产品B: 80 },
{ 月份: '2月', 产品A: 150, 产品B: 120 },
{ 月份: '3月', 产品A: 120, 产品B: 100 }
];
const column = new Column('columnChart', {
data,
xField: '月份',
yField: ['产品A', '产品B'],
isGroup: true // 分组显示
});
column.render();
2.5 饼图
2.5.1 基础饼图
作用:展示数据的占比关系
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import { Pie } from '@antv/g2plot';
const data = [
{ type: '类型A', value: 30 },
{ type: '类型B', value: 25 },
{ type: '类型C', value: 20 },
{ type: '类型D', value: 25 }
];
const pie = new Pie('pieChart', {
data,
angleField: 'value', // 角度字段
colorField: 'type', // 颜色字段
label: {
type: 'outer',
content: '{name} {percentage}'
}
});
pie.render();
2.6 图表配置选项
常用配置:
| 配置项 | 说明 | 示例 |
|---|---|---|
title |
图表标题 | title: { text: '销售趋势' } |
legend |
图例 | legend: { position: 'top' } |
color |
颜色 | color: '#3498db' |
label |
标签 | label: { position: 'top' } |
tooltip |
提示框 | tooltip: { showMarkers: true } |
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18const line = new Line('lineChart', {
data,
xField: 'month',
yField: 'value',
title: {
text: '销售趋势图',
style: {
fontSize: 16
}
},
legend: {
position: 'top-right'
},
color: '#3498db',
tooltip: {
showMarkers: true
}
});
3. 数据看板开发
3.1 什么是数据看板?
数据看板 = 多个图表组合在一起,全面展示数据
生活类比:
- 单个图表 = 一张照片(只能看一个角度)
- 数据看板 = 多张照片拼成的全景图(能看到全貌)
实际例子:
1 | 数据看板包含: |
3.2 看板布局设计
3.2.1 使用Ant Design Vue布局
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50<template>
<a-layout>
<a-layout-header>
<h1>数据看板</h1>
</a-layout-header>
<a-layout-content style="padding: 24px;">
<!-- 关键指标 -->
<a-row :gutter="16" style="margin-bottom: 24px;">
<a-col :span="6">
<a-card>
<h3>总销售额</h3>
<p style="font-size: 24px;">¥100,000</p>
</a-card>
</a-col>
<a-col :span="6">
<a-card>
<h3>总用户数</h3>
<p style="font-size: 24px;">1,234</p>
</a-card>
</a-col>
<a-col :span="6">
<a-card>
<h3>订单数</h3>
<p style="font-size: 24px;">567</p>
</a-card>
</a-col>
<a-col :span="6">
<a-card>
<h3>增长率</h3>
<p style="font-size: 24px;">+12.5%</p>
</a-card>
</a-col>
</a-row>
<!-- 图表区域 -->
<a-row :gutter="16">
<a-col :span="12">
<a-card title="销售趋势">
<div id="lineChart"></div>
</a-card>
</a-col>
<a-col :span="12">
<a-card title="产品分布">
<div id="pieChart"></div>
</a-card>
</a-col>
</a-row>
</a-layout-content>
</a-layout>
</template>
3.3 完整看板示例
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94<template>
<div class="dashboard">
<h1>数据看板</h1>
<!-- 关键指标卡片 -->
<a-row :gutter="16" class="stats-row">
<a-col :span="6" v-for="stat in stats" :key="stat.title">
<a-card>
<h3>{{ stat.title }}</h3>
<p class="stat-value">{{ stat.value }}</p>
<span :class="stat.trend > 0 ? 'trend-up' : 'trend-down'">
{{ stat.trend > 0 ? '↑' : '↓' }} {{ Math.abs(stat.trend) }}%
</span>
</a-card>
</a-col>
</a-row>
<!-- 图表区域 -->
<a-row :gutter="16" class="charts-row">
<a-col :span="12">
<a-card title="销售趋势">
<div id="salesChart" style="height: 300px;"></div>
</a-card>
</a-col>
<a-col :span="12">
<a-card title="产品销量">
<div id="productChart" style="height: 300px;"></div>
</a-card>
</a-col>
</a-row>
</div>
</template>
<script>
import { Line, Column } from '@antv/g2plot';
import { onMounted, ref } from 'vue';
export default {
setup() {
const stats = ref([
{ title: '总销售额', value: '¥100,000', trend: 12.5 },
{ title: '总用户数', value: '1,234', trend: 8.3 },
{ title: '订单数', value: '567', trend: -2.1 },
{ title: '增长率', value: '+12.5%', trend: 5.2 }
]);
onMounted(() => {
// 销售趋势图
const salesData = [
{ month: '1月', value: 1000 },
{ month: '2月', value: 1500 },
{ month: '3月', value: 1200 }
];
const salesChart = new Line('salesChart', {
data: salesData,
xField: 'month',
yField: 'value'
});
salesChart.render();
// 产品销量图
const productData = [
{ 产品: '产品A', 销量: 100 },
{ 产品: '产品B', 销量: 150 },
{ 产品: '产品C', 销量: 120 }
];
const productChart = new Column('productChart', {
data: productData,
xField: '产品',
yField: '销量'
});
productChart.render();
});
return {
stats
};
}
};
</script>
<style scoped>
.stat-value {
font-size: 24px;
font-weight: bold;
margin: 10px 0;
}
.trend-up {
color: #52c41a;
}
.trend-down {
color: #ff4d4f;
}
</style>
4. 动态数据更新
4.1 实时更新图表数据
场景:数据从API获取,需要实时更新图表
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40import { Line } from '@antv/g2plot';
import { onMounted, ref } from 'vue';
import { getSalesData } from '@/api/sales';
export default {
setup() {
const chartRef = ref(null);
onMounted(async () => {
// 初始化图表
const chart = new Line('chart', {
data: [],
xField: 'month',
yField: 'value'
});
chart.render();
chartRef.value = chart;
// 加载数据
await loadData();
});
// 加载数据
const loadData = async () => {
try {
const data = await getSalesData();
// 更新图表数据
chartRef.value.update({
data: data
});
} catch (error) {
console.error('加载数据失败', error);
}
};
return {
loadData
};
}
};
4.2 定时刷新数据
作用:每隔一段时间自动更新数据
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24import { onMounted, onUnmounted } from 'vue';
export default {
setup() {
let timer = null;
onMounted(() => {
// 立即加载一次
loadData();
// 每30秒刷新一次
timer = setInterval(() => {
loadData();
}, 30000);
});
onUnmounted(() => {
// 组件销毁时清除定时器
if (timer) {
clearInterval(timer);
}
});
}
};
4.3 响应式更新
作用:窗口大小改变时,图表自动调整
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24import { onMounted, onUnmounted } from 'vue';
export default {
setup() {
const chartRef = ref(null);
const handleResize = () => {
if (chartRef.value) {
chartRef.value.changeSize(
document.getElementById('chart').offsetWidth,
300
);
}
};
onMounted(() => {
window.addEventListener('resize', handleResize);
});
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
});
}
};
5. AI实战:使用AI生成数据看板
5.1 任务描述
目标:使用AI工具生成一个完整的数据看板
功能要求:
- 使用Ant Design Vue布局
- 显示关键指标卡片(4个)
- 包含折线图(销售趋势)
- 包含柱状图(产品销量)
- 包含饼图(类别分布)
- 数据从API获取(模拟数据也可以)
- 样式美观,响应式布局
5.2 第一步:设计Prompt
Prompt示例: 1
2
3
4
5
6
7
8
9
10用Vue 3和Ant Design Vue创建一个数据看板,要求:
1. 使用Ant Design Vue的Layout和Card组件
2. 顶部显示4个关键指标卡片(总销售额、总用户数、订单数、增长率)
3. 中间区域包含3个图表:
- 折线图:销售趋势(使用G2Plot)
- 柱状图:产品销量(使用G2Plot)
- 饼图:类别分布(使用G2Plot)
4. 使用响应式布局,适配不同屏幕
5. 图表数据使用模拟数据
6. 代码注释清晰,样式美观
5.3 AI生成的代码(示例)
1 | <template> |
5.4 代码解析
核心思路:
- 布局设计:使用Ant Design Vue的Layout和Grid系统
- 关键指标:用Card组件展示统计数据
- 图表集成:使用G2Plot创建各种图表
- 响应式:使用Ant Design Vue的响应式栅格
关键点:
- 使用
onMounted生命周期初始化图表 - 图表容器需要指定ID和高度
- 响应式布局适配不同屏幕
6. 选讲:可视化组件开发
6.1 封装图表组件
6.1.1 为什么需要封装?
问题:每个页面都要重复写图表初始化代码
解决方案:封装成可复用的组件
6.1.2 创建图表组件
实际例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72<!-- components/ChartLine.vue -->
<template>
<div :id="chartId" :style="{ height: height + 'px' }"></div>
</template>
<script>
import { Line } from '@antv/g2plot';
import { onMounted, watch, onBeforeUnmount } from 'vue';
export default {
name: 'ChartLine',
props: {
data: {
type: Array,
required: true
},
xField: {
type: String,
default: 'x'
},
yField: {
type: String,
default: 'y'
},
height: {
type: Number,
default: 300
}
},
setup(props) {
const chartId = `line-chart-${Date.now()}`;
let chartInstance = null;
const initChart = () => {
if (chartInstance) {
chartInstance.destroy();
}
chartInstance = new Line(chartId, {
data: props.data,
xField: props.xField,
yField: props.yField
});
chartInstance.render();
};
onMounted(() => {
initChart();
});
// 监听数据变化,更新图表
watch(() => props.data, () => {
if (chartInstance) {
chartInstance.update({
data: props.data
});
}
}, { deep: true });
onBeforeUnmount(() => {
if (chartInstance) {
chartInstance.destroy();
}
});
return {
chartId
};
}
};
</script>
使用方式: 1
2
3
4
5
6
7<template>
<ChartLine
:data="salesData"
x-field="month"
y-field="value"
:height="300" />
</template>
6.2 可视化设计原则
6.2.1 选择合适的图表类型
| 数据类型 | 推荐图表 | 说明 |
|---|---|---|
| 趋势数据 | 折线图 | 展示数据随时间的变化 |
| 对比数据 | 柱状图 | 对比不同类别的数值 |
| 占比数据 | 饼图 | 展示各部分占比 |
| 分布数据 | 散点图 | 展示数据分布情况 |
6.2.2 颜色使用原则
原则:
- 主色调统一:整个看板使用统一的配色方案
- 对比明显:不同数据系列颜色要有区分度
- 避免过多颜色:一般不超过5-7种颜色
实际例子: 1
2
3
4
5
6
7// 推荐:使用统一的颜色方案
const colors = ['#3498db', '#52c41a', '#ff4d4f', '#faad14'];
const chart = new Line('chart', {
data,
color: colors[0] // 使用统一的颜色
});
6.2.3 数据展示策略
原则:
- 突出重点:重要数据用大字体、醒目颜色
- 层次清晰:标题、数据、说明层次分明
- 信息适量:不要一次展示太多信息
实际例子: 1
2
3
4
5
6<!-- 好的设计:层次清晰 -->
<a-card>
<h3>总销售额</h3> <!-- 标题 -->
<p class="stat-value">¥100,000</p> <!-- 主要数据 -->
<span class="trend">↑ 12.5%</span> <!-- 辅助信息 -->
</a-card>
6.3 G2与G2Plot的关系
G2 = 底层的图形语法库
- 特点:更灵活,可以自定义任何图表
- 适用:需要高度自定义的场景
- 难度:学习曲线较陡
G2Plot = 基于G2的高级封装
- 特点:简单易用,开箱即用
- 适用:常见的业务图表场景
- 难度:学习曲线平缓
关系: 1
2
3
4
5G2(底层,灵活但复杂)
↓
G2Plot(高级封装,简单易用)
↓
Ant Design Vue(UI组件库集成)
💡 建议:
对于初学者和大多数业务场景,使用G2Plot就足够了。
只有在需要高度自定义图表时,才考虑使用G2。
本章总结
通过本章的学习,你已经掌握了:
✅ 图表库使用:
- G2Plot的基础使用
- 折线图、柱状图、饼图的创建
- 图表配置选项
✅ 数据看板开发:
- 使用Ant Design Vue布局
- 关键指标卡片展示
- 多图表组合
✅ 动态数据更新:
- 实时更新图表数据
- 定时刷新机制
- 响应式调整
✅ 实战技能:
- 构建完整的数据看板
- 使用AI生成代码
- 封装图表组件
✅ 进阶知识(选讲):
- 可视化设计原则
- 图表组件封装
- G2与G2Plot的关系
🌟 恭喜你!
你已经掌握了数据可视化的核心技能!
这些知识将帮助你:
实现数据统计和展示
构建专业的数据看板
提升用户体验
继续练习,继续探索,数据可视化的世界等着你! 🚀