AntChart

记录 AntChart 的基本用法

图表

图表不是必须的,但好看的图表,是一个产品中的亮点。

1. 概述

1.1 组件的选择

蚂蚁金服关于图表控件很多,可以分为三类:

  • 基础产品
  • 扩展产品
  • React 产品:Ant Design Charts
  • StatisticCard 指标卡

G2G2PlotAnt Design Charts 什么关系?

  • 同一团队开发。
  • G2G2Plot 的底层依赖,使用了图形语法,使用成本相对较高,功能强大。
  • G2PlotG2 的上层封装,把图形语法装换成了配置项。
  • Ant Design ChartsG2Plot 的 React 版本,功能和 G2Plot 同步,并内置了一些图相关的图表,例如流程图、组织架构图等。
  • 其它一些图表是其它团队的同学基于 G2G2Plot 实现。

这里还有一个bizchartsAnt Design Pro中使用,不知道会不会被淘汰。

1.2 推荐组件

  • StatisticCard 指标卡

  • Ant Design Charts 可以在程序中用

  • X6 做一些流程图

  • G6做一些大数据分析用

Ant Design Charts能满足日常的基本使用,更方便与快捷。

1.3 参考文档

2. 公用方法

2.1 快速开始

安装

tyarn add @ant-design/charts

2.2 常用属性

① statistic

statistic:统计量。

如下图中的:进度 60.00% 就是统计信息。可以参考这个文档

可以设置的内容有:

  • title
  • content

例如下面的例子,设置了 title。 这里使用了formatter,当然也可以使用优先级更高的customHtml, 但是还不知道customHtml怎么用。

const DemoRingProgress: React.FC = () => {
var config = {
height: 100,
width: 100,
autoFit: false,
percent: 0.6,
color: ['#F4664A', '#E8EDF3'],
innerRadius: 0.85,
radius: 0.98,
statistic: {
title: {
style: {
color: '#363636',
fontSize: '12px',
lineHeight: '14px',
},
formatter: function formatter() {
return '进度';
},
},
},
};
return <RingProgress {...config} />;
};

② annotations

annotations:空间标注。

强行在图上添加一个元素。

③ Tooltip

tooltip:工具提示

鼠标移动到某个节点,可以看到提示信息,具体参考这个文档

④ meta

2.3 基本方法

① 下载图片

可以导出图片,具体见这个文档

③ 绑定事件

鼠标点击图片上的元素时,可以获取相应的属性,具体见

④ 获取 char 实例

通过得到实例,可以调用控件中的方法。具体参考这个文档

⑤ 自定义 shape

这个没有看明白,具体可以研究一下这个文档

2.4 绘图属性

可以参考这个文档

3. 迷你图

这里用到了三个迷你图:

  • 迷你面积图
  • 迷你柱状图
  • 进度条图

关键点:

  • 自定义的提示信息
  • 指定不同颜色
  • 可以自适应宽度
  • 指定固定高度

迷你图的注意事项(与正常图片的区别):

  • Data 只能时 number[],不能指定 X Y 。

3.1 迷你面积图

访问量这个图表的代码如下:

import React from 'react';
import { TinyArea } from '@ant-design/charts';
import Tip from '../Tip';
import { fakeVisitData } from '../../../service';
// 得到模拟的数据
const visitData = fakeVisitData();
const TinyAreaVisits: React.FC = () => {
// 必须返回一个number[]
const data = visitData.map(item => item.value);
const config = {
height: 60,
data,
smooth: true,
// 指定填充的颜色
areaStyle: { fill: '#975fe4' },
// 为了好看,将线的颜色变成了与背景颜色一样了。
line: { color: '#fff' },
// 按照自定义Tip来显示提示信息
tooltip: {
customContent: function customContent(index: number, items: any) {
if (!visitData[index]) {
return '';
}
return (
<Tip
title={visitData[index].date}
value={visitData[index].value}
color="#975fe4"
/>
);
},
},
};
return <TinyArea {...config} />;
};
export default TinyAreaVisits;

①②③④⑤⑥⑦⑧⑨

3.2 迷你柱状图

支付笔数,是一个柱状图,用下面的代码实现。

import React from 'react';
import { TinyColumn } from '@ant-design/charts';
import Tip from '../Tip';
import { fakeVisitData } from '../../../service';
// 得到模拟的数据
const visitData = fakeVisitData();
const TinyColumnPay: React.FC = () => {
// 必须返回一个number[]
const data = visitData.map(item => item.value);
const config = {
height: 60,
data,
// 按照自定义一个组建叫Tip,来显示提示信息
tooltip: {
customContent: function customContent(index: number, items: any) {
if (!visitData[index]) {
return '';
}
return (
<Tip
title={visitData[index].date}
value={visitData[index].value}
color={items[0].color}
/>
);
},
},
};
return <TinyColumn {...config} />;
};
export default TinyColumnPay;

3.3 迷你进度条图

这里的关键点是

  • 如何设置进度条的高度,方法有点绕。
  • 如何设置目标值

这个问题还是在github学习的,这里是具体的咨询过程

代码

import React from 'react';
import { Progress } from '@ant-design/charts';
const TinyProgressActive: React.FC = () => {
const config = {
height: 60,
percent: 0.736,
// 框的大小
barWidthRatio: 0.25,
color: ['#13c2c2', '#E8EDF3'],
// 这个用来显示目标值,里面还有很多属性需要熟悉
annotations: [
{
type: 'line',
start: ['80%', '30%'],
end: ['80%', '70%'],
top: false,
style: {
stroke: '#13c2c2',
lineWidth: 2,
},
},
],
};
// @ts-ignore
return <Progress {...config} />;
};
export default TinyProgressActive;

3.4 迷你进度环图

官方例子

希望做成的样子

圆中心没有文字显示。

代码

import React from 'react';
import { Col, Row } from 'antd';
import NumberInfo from '../NumberInfo';
import { RingProgress } from '@ant-design/charts';
import type { OfflineDataType } from '../../service';
type CustomTabProps = {
data: OfflineDataType;
};
export default (props: CustomTabProps) => {
const { data } = props;
var config = {
height: 60,
width: 60,
autoFit: false,
percent: data.cvr,
color: ['#58afff', '#E8EDF3'],
// 控制环的代销
innerRadius: 0.7,
radius: 0.98,
// 不显示中间那部分内容
statistic: {
content: false,
},
};
return (
<Row>
<Col span={12}>
<NumberInfo title={data.name} subTitle="转化率" gap={2} total={`${data.cvr * 100}%`} />
</Col>
<Col span={12} style={{ paddingTop: 36 }}>
<RingProgress {...config} />
</Col>
</Row>
);
};

4. 常用图形

4.1 环形图

案例

例如做出下面的样子,也是在网上问的

我撰写的代码

import React from 'react';
import { Pie } from '@ant-design/charts';
import accounting from 'accounting';
type PieSalesProps = {
data: { x: string; y: number }[];
};
const PieSales: React.FC<PieSalesProps> = (props: PieSalesProps) => {
const { data } = props;
const getY = (x: string) => {
for (let i = 0; i < data.length; i += 1) {
if (data[i].x === x) {
return data[i].y;
}
}
return 0;
};
const config = {
appendPadding: 10,
data,
height: 400 - 50,
// 弧度对应的字段
angleField: 'y',
// 颜色对应的字段
colorField: 'x',
// 饼图的半径,原点为画布中心。配置值域为 (0,1],1 代表饼图撑满绘图区域。
radius: 0.68,
// 饼图的内半径,原点为画布中心。配置值域为 (0,1] ,通过设置这个来做镂空图形
innerRadius: 0.8,
// 全局化配置图表数据元信息,以字段为单位进行配置
meta: {
x: {
formatter: (v: string) => {
return `${v} ${accounting.formatMoney(getY(v), '¥', 0)}`;
},
},
// 将金额设定成Money的格式
y: {
formatter: (v: number) => {
return `${accounting.formatMoney(v, '¥', 0)}`;
},
},
},
// 状态的属性
state: {
active: {
style: {
stroke: '#fff',
},
},
},
// 每个pie的间隔变大
pieStyle: {
stroke: '#fff',
lineWidth: 4,
},
// 不在弧度上显示明细
label: {
content: '',
},
// 图表交互
interactions: [
{ type: 'element-selected' },
{ type: 'element-active' },
{ type: 'pie-statistic-active' },
],
};
// @ts-ignore
return <Pie {...config} />;
};
export default PieSales;

网友提供的代码

https://codesandbox.io/s/gifted-lehmann-63vhs?file=/App.tsx:873-1021

其中可以给汇总信息定义样式

statistic: {
title: {
formatter: () => 'title'
},
content: {
style: {
whiteSpace: 'pre-wrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
fontSize:10,
},
formatter: () => 'AntV',
},
},

4.2 雷达图

官方的例子

原始数据文件,然后经过转换,转成雷达图要的数据结构

[
{ "item": "Design", "a": 70, "b": 30 },
{ "item": "Development", "a": 60, "b": 70 },
{ "item": "Marketing", "a": 50, "b": 60 },
{ "item": "Users", "a": 40, "b": 50 },
{ "item": "Test", "a": 60, "b": 70 },
{ "item": "Language", "a": 70, "b": 50 },
{ "item": "Technology", "a": 50, "b": 40 },
{ "item": "Support", "a": 30, "b": 40 },
{ "item": "Sales", "a": 60, "b": 40 },
{ "item": "UX", "a": 50, "b": 60 }
]

转换的代码

const [data, setData] = useState([]);
useEffect(() => {
asyncFetch();
}, []);
const asyncFetch = () => {
fetch(
'https://gw.alipayobjects.com/os/bmw-prod/bda695a8-cd9f-4b78-a423-3d6d547c10c3.json',
)
.then(response => response.json())
.then(json => setData(json))
.catch(error => {
console.log('fetch data failed', error);
});
};
const { DataView } = DataSet;
const dv = new DataView().source(data);
dv.transform({
type: 'fold',
fields: ['a', 'b'], // 展开字段集
key: 'user', // key字段
value: 'score', // value字段
});