-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
34a47de
commit 89b5b99
Showing
2 changed files
with
340 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,336 @@ | ||
# G2 | ||
|
||
G2官网:https://g2.antv.antgroup.com/manual/introduction/what-is-g2 | ||
|
||
语雀知源.致远:https://www.yuque.com/afx/blog/fpgdp5 | ||
|
||
林峰:`Echarts`的作者 | ||
G2 是面粉,Echarts 是面条,皆微小而美好,因小食材怀大梦想,助力共筹东方巨龙崛起之盛宴,迎四海饕客。 | ||
|
||
我们是蚂蚁集团数据可视化团队,一群有爱有梦的人,怀揣「让人们在数据世界里获得视觉化思考能力」的梦想前行,成就智能时代全球领先的数据可视化解决方案。 | ||
|
||
多年前第一次看到`知源.致远`这篇文章的时候真的是羡慕这样的团队。可即使是这么优秀、这么纯粹的一个研发团队,也最终会走向没落。技术人员的出路到底是什么? | ||
|
||
```ts | ||
TODO:学了`webgl`的渲染以后,现在看G2的源码好像没有那么恐怖了,后面有时间还是要学习学习。也不需要学习它的底层代码,但是它作为一个这么好用的图表库,有时间还是需要好好研究研究。 | ||
``` | ||
|
||
## G2学习 | ||
`G2`是一个简洁的渐进式语法,主要用于制作基于网页的可视化。它提供了一套函数风格式、声明形式的API和组件化的编程范式,希望能帮助用户能快速完成`报表搭建、数据探索、可视化叙事`等多样式的需求。 | ||
|
||
`G2`中的核心概念: | ||
- 标记(Mark): 绘制数据驱动的图形 | ||
- 转换(Transform): 派生数据 | ||
- 比例尺(Scale): 将抽象的数据映射为视觉数据 | ||
- 坐标系(Coordinate): 对空间通道应用点变换 | ||
- 视图复合(Composition): 管理和增强视图 | ||
- 动画(Animation): 数据驱动的动画和连续的形变动画 | ||
- 交互(Interaction): 操作视图并且展现详细信息 | ||
|
||
## 安装 | ||
```ts | ||
npm install @antv/g2 | ||
|
||
// 安装依赖时报错: | ||
Fix the upstream dependency conflict, or retry | ||
npm ERR! this command with --force, or --legacy-peer-deps | ||
npm ERR! to accept an incorrect (and potentially broken) dependency resolution | ||
// 当前的依赖项和之前安装的某些包需求的依赖项有冲突,在后面加上 --force 或 --legacy-peer-deps | ||
// 然后按提示执行npm audit fix --force | ||
|
||
// 后续又换了一个干净的vue3项目,没有上诉依赖冲突的报错问题 | ||
``` | ||
|
||
## 绘制第一张图表 | ||
```vue | ||
<script setup lang="ts"> | ||
import { onMounted } from 'vue' | ||
import { Chart } from '@antv/g2'; | ||
// 准备数据 | ||
const data = [ | ||
{ genre: 'Sports', sold: 275 }, | ||
{ genre: 'Strategy', sold: 115 }, | ||
{ genre: 'Action', sold: 120 }, | ||
{ genre: 'Shooter', sold: 350 }, | ||
{ genre: 'Other', sold: 150 } | ||
] | ||
onMounted(() => { | ||
// 初始化图表实例 | ||
const chart = new Chart({ | ||
width: 800, // 图表高度 | ||
height: 400, // 图表宽度 | ||
container: 'container', // 挂载容器的ID | ||
}) | ||
// 声明可视化 | ||
chart | ||
.interval() // 创建一个 Interval 标记 | ||
.data(data) // 绑定数据 | ||
.encode('x', 'genre') // 编码 x 通道 | ||
.encode('y', 'sold') // 编码 y 通道 | ||
// 渲染可视化 | ||
chart.render() | ||
}) | ||
</script> | ||
<template> | ||
<div id="container"></div> | ||
</template> | ||
``` | ||
|
||
## 使用复合节点在一个容器中绘制两张图表 | ||
可参考下面的使用复合`Mark`进行代码优化 | ||
```vue | ||
<script setup lang="ts"> | ||
import { onMounted } from 'vue' | ||
import { Chart } from '@antv/g2'; | ||
// 准备数据 | ||
const data = [ | ||
{ genre: 'Sports', sold: 350 }, | ||
{ genre: 'Strategy', sold: 275 }, | ||
{ genre: 'Action', sold: 150 }, | ||
{ genre: 'Shooter', sold: 120 }, | ||
{ genre: 'Other', sold: 115 } | ||
] | ||
onMounted(() => { | ||
// 初始化图表实例 | ||
const chart = new Chart({ | ||
width: 800, // 图表高度 | ||
height: 400, // 图表宽度 | ||
container: 'container', // 挂载容器的ID | ||
}) | ||
chart.options({ | ||
type: 'spaceFlex', // 复合节点 | ||
children: [ | ||
{ | ||
type: 'interval', | ||
padding: 'auto', | ||
data: data, | ||
encode: { | ||
x: 'genre', // 编码 x 通道 | ||
y: 'sold' // 编码 y 通道 | ||
} | ||
}, | ||
{ | ||
type: 'interval', | ||
padding: 'auto', | ||
data: data, | ||
encode: { | ||
color: 'genre', // 编码 x 通道 | ||
y: 'sold' // 编码 y 通道 | ||
}, | ||
transform: [{ type: 'stackY' }], | ||
coordinate: { type: 'theta' }, | ||
legend: { color: false } | ||
} | ||
] | ||
}) | ||
// 渲染可视化 | ||
chart.render() | ||
}) | ||
</script> | ||
<template> | ||
<div id="container"></div> | ||
</template> | ||
``` | ||
|
||
## 请求json文件作为数据源 | ||
```vue | ||
<script setup lang="ts"> | ||
import { onMounted } from 'vue' | ||
import { Chart } from '@antv/g2'; | ||
onMounted(() => { | ||
// 初始化图表实例 | ||
const chart = new Chart({ | ||
width: 800, // 图表高度 | ||
height: 400, // 图表宽度 | ||
container: 'container', // 挂载容器的ID | ||
}) | ||
chart.options({ | ||
type: 'point', | ||
data: { | ||
type: 'fetch', | ||
value: 'https://gw.alipayobjects.com/os/basement_prod/6b4aa721-b039-49b9-99d8-540b3f87d339.json' | ||
}, | ||
encode: { | ||
color: 'gender', | ||
x: 'height', | ||
y: 'weight', | ||
} | ||
}) | ||
// 渲染可视化 | ||
chart.render() | ||
}) | ||
</script> | ||
<template> | ||
<div id="container"></div> | ||
</template> | ||
``` | ||
|
||
## 图表数据叠加 | ||
```vue | ||
<script setup lang="ts"> | ||
import { onMounted } from 'vue' | ||
import { Chart } from '@antv/g2'; | ||
onMounted(() => { | ||
// 初始化图表实例 | ||
const chart = new Chart({ | ||
width: 800, // 图表高度 | ||
height: 400, // 图表宽度 | ||
container: 'container', // 挂载容器的ID | ||
}) | ||
chart.options({ | ||
type: 'line', | ||
data: { | ||
type: 'fetch', | ||
value: 'https://assets.antv.antgroup.com/g2/indices.json' | ||
}, | ||
transform: [{ | ||
type: 'normalizeY', | ||
basis: 'first', | ||
groupBy: 'color' | ||
}], | ||
encode: { | ||
x: (d: any) => new Date(d.Date), | ||
color: 'Symbol', | ||
y: 'Close', | ||
}, | ||
axis: { | ||
y: { | ||
title: '↑ Change in price (%)' | ||
} | ||
} | ||
}) | ||
// 渲染可视化 | ||
chart.render() | ||
}) | ||
</script> | ||
<template> | ||
<div id="container"></div> | ||
</template> | ||
``` | ||
|
||
## 使用复合 Mark | ||
```vue | ||
<script setup lang="ts"> | ||
import { onMounted } from 'vue' | ||
import { Chart } from '@antv/g2'; | ||
const data = [ | ||
{ year: '1991', value: 3 }, | ||
{ year: '1992', value: 4 }, | ||
{ year: '1993', value: 3.5 }, | ||
{ year: '1994', value: 5 }, | ||
{ year: '1995', value: 4.9 }, | ||
{ year: '1996', value: 6 }, | ||
{ year: '1997', value: 7 }, | ||
{ year: '1998', value: 9 }, | ||
{ year: '1999', value: 13 }, | ||
] | ||
onMounted(() => { | ||
// 初始化图表实例 | ||
const chart = new Chart({ | ||
width: 800, // 图表高度 | ||
height: 400, // 图表宽度 | ||
container: 'container', // 挂载容器的ID | ||
}) | ||
// 定义复合 Mark | ||
function PointLine({ encode, data }: any = {}) { | ||
return [ | ||
{ type: 'line', data, encode }, | ||
{ type: 'point', data, encode }, | ||
] | ||
} | ||
chart.options({ | ||
type: PointLine, // 使用复合 Mark | ||
data, | ||
encode: { | ||
x: 'year', | ||
y: 'value' | ||
} | ||
}) | ||
// 渲染可视化 | ||
chart.render() | ||
}) | ||
</script> | ||
<template> | ||
<div id="container"></div> | ||
</template> | ||
``` | ||
|
||
|
||
## 桑基图绘制 | ||
桑基图最明显的特征就是:始末端的分支宽度总和相等,即所有主支宽度的总和应与所有分出去的分支宽度的总和相等,保持能量的平衡。 | ||
在这个案例中,json文件的数据格式:绘制桑基图来说,这种数据格式应该是固定的。 | ||
```json | ||
{ | ||
"source": "Agricultural 'waste'", // 来源 | ||
"target": "Bio-conversion", // 目标 | ||
"value": 124.729 // 数值 | ||
}, | ||
``` | ||
|
||
```vue | ||
<script setup lang="ts"> | ||
import { onMounted } from 'vue' | ||
import { Chart } from '@antv/g2'; | ||
onMounted(() => { | ||
// 初始化图表实例 | ||
const chart = new Chart({ | ||
width: 900, // 图表高度 | ||
height: 600, // 图表宽度 | ||
container: 'container', // 挂载容器的ID | ||
}) | ||
chart.options({ | ||
type: 'sankey', | ||
data: { | ||
type: 'fetch', | ||
value: 'https://assets.antv.antgroup.com/g2/energy.json', | ||
transform: [ | ||
{ | ||
type: 'custom', | ||
callback: (data: any) => ({ links: data }), | ||
} | ||
] | ||
}, | ||
layout: { | ||
nodeAlign: 'center', | ||
nodePadding: 0.03 | ||
}, | ||
style: { | ||
labelSpacing: 3, | ||
labelFontWeight: 'bold', | ||
nodeStrokeWidth: 1.2, | ||
linkFillOpacity: 0.4 | ||
} | ||
}) | ||
// 渲染可视化 | ||
chart.render() | ||
}) | ||
</script> | ||
<template> | ||
<div id="container"></div> | ||
</template> | ||
``` |