Skip to content

Commit

Permalink
新增G2的学习
Browse files Browse the repository at this point in the history
  • Loading branch information
chaochao2-0 committed Oct 26, 2023
1 parent 34a47de commit 89b5b99
Show file tree
Hide file tree
Showing 2 changed files with 340 additions and 0 deletions.
4 changes: 4 additions & 0 deletions docs/.vitepress/sidebar.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
{
"text": "2023",
"items": [
{
"text": "G2学习",
"link": "/2023/G2学习"
},
{
"text": "flutter",
"items": [
Expand Down
336 changes: 336 additions & 0 deletions docs/2023/G2学习.md
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>
```

0 comments on commit 89b5b99

Please sign in to comment.