echarts在react中的使用

本文的所有示例都可以在 react-admin(test:test)下查看体验

注意事项

  1. echarts 获取的 dom 结构必须要设置具体的高度或者宽度,这样 echarts 对应的 canvas 画布才有大小显示。
  2. echarts 的有效数值 必须是数值,这样才会显示正确的值,比如 y = 12(或者”12”) 而不能是”12s”这种,如果 y 轴需要带单位可以在 series 的 label 属性的 formater 进行配置单位显示。
  3. echarts 数据集如果不设置有效的映射,那么 echarts 将根据数据集对象的键顺序判断谁是 x 轴 谁是 y 轴。 如下面的例子: value 是第一个键,那么 echarts 就将其映射为 x 轴,name 对应的就会映射到 y 轴,根据 2,有效值的地方必须是数字,所以 echarts 将不会显示图像,需要将 value 和 name 这两个键的顺序交换。
1
2
3
4
5
6
7
8
9
10
const dataset.source = [
{
"value": "120",
"name": "星期一"
},
{
"value": "130",
"name": "星期二"
}
]
  1. 实际开发时调节 echarts 时最好直接在 echarts 提供的示例中进行修改,这样效率较高。
  2. 对于开发中需要的配置项不清楚时,可在术语速查手册中根据图例快速找到配置项.
  3. echarts 的配置项众多,建议使用 ts 的类型提示,option 的类型是 echarts.EChartsCoreOption。
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
const options: echarts.EChartsCoreOption = {
title: {
text: "饼图",
left: "center",
},
legend: {
orient: "vertical",
left: "left",
},
tooltip: {
trigger: "item",
},
series: [
{
name: "value",
type: "pie",
// 饼图中radius决定大小
radius: "80%",
// 决定图示在饼图上的位置
// label: {
// show: true,
// position: "inside",
// formatter: (params: any) => {
// return `${params.data.name}:${params.data.value}`;
// },
// color: "#fff"
// },
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: "rgba(0, 0, 0, 0.5)",
},
},
// top right 饼图在画布中的位置
top: 40,
},
],
};

echarts 数据集

在实际开发过程中,echarts 的样式配置实际是很少变化的,变化较多的实际是其数据,为了将数据和配置较好的分离,使用 echarts 的 dataset 是较为合适的方案

实际开发过程中,个人觉得采用对象数组的数据源更为符合直觉,这里以一个二维的图进行举例

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
// 二维数据需要设计维度dataset.dimensions

const dimensions = ["name", "eatMoney", "entertainmentMoney"];

// dataset.source
const initialLineData = [
{
name: "星期一",
eatMoney: 120,
entertainmentMoney: 30,
},
{
name: "星期二",
eatMoney: 132,
entertainmentMoney: 25,
},
{
name: "星期三",
eatMoney: 101,
entertainmentMoney: 50,
},
{
name: "星期四",
eatMoney: 134,
entertainmentMoney: 55,
},
{
name: "星期五",
eatMoney: 90,
entertainmentMoney: 90,
},
{
name: "星期六",
eatMoney: 230,
entertainmentMoney: 88,
},
{
name: "星期日",
eatMoney: 210,
entertainmentMoney: 130,
},
];

useEcharts 的封装

在 echarts 的使用过程中,发现每个组件在使用中都需要进行配置初始化、监听 resize 事件,在组件销毁时都要注销事件监听、在数据源发生变化时重新设置配置,因此将其选择封装为一个 hook,暴露 echarts 需要的 ref 即可。

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
import * as echarts from "echarts";
import { useEffect, useRef } from "react";
/**
* @description 使用Echarts(只是为了添加图表响应式)
* @param {Element} data 数据 目前只针对于次Hooks-admin里一些data都是写死在options 所以data为可选 根据项目自行修改即可
* @param {Object} options 绘制Echarts的参数(必传)
* @return chart
* */
export const useEcharts = (
options: echarts.EChartsCoreOption,
data: Record<string, any>[]
) => {
const myChart = useRef<echarts.EChartsType>();
const echartsRef = useRef<HTMLDivElement>(null);

// 视图变化时 echarts也视图对应改变
const echartsResize = () => {
echartsRef && myChart?.current?.resize();
};
// 数据发生变化时重新绘制
useEffect(() => {
if (data?.length !== 0) {
options.dataset || (options.dataset = {});
(options.dataset as Record<string, any>).source = data;
myChart?.current?.setOption(options);
}
}, [data, options]);
// 初始化设置 初始化显示 初始化事件监听 以及设置组件销毁时 移除事件监听
useEffect(() => {
if (echartsRef?.current) {
myChart.current = echarts.init(echartsRef.current as HTMLDivElement);
}
myChart?.current?.setOption(options);
window.addEventListener("resize", echartsResize, false);
return () => {
window.removeEventListener("resize", echartsResize);
myChart?.current?.dispose();
};
}, []);

return [echartsRef];
};

使用

  1. 提供一个带有高度或者宽度的 html 标签 如 div
  2. 提供初始数据
  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
// PieChart.tsx
import { useEcharts } from "../../../../hooks/useEcharts";
const options: echarts.EChartsCoreOption = {
title: {
text: "饼图",
left: "center",
},
legend: {
orient: "vertical",
left: "left",
},
tooltip: {
trigger: "item",
},
series: [
{
name: "value",
type: "pie",
// 饼图中radius决定大小
radius: "80%",
// 决定图示在饼图上的位置
// label: {
// show: true,
// position: "inside",
// formatter: (params: any) => {
// return `${params.data.name}:${params.data.value}`;
// },
// color: "#fff"
// },
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: "rgba(0, 0, 0, 0.5)",
},
},
// top right 饼图在画布中的位置
top: 40,
},
],
};

const PieChart = ({ data }: { data: Record<string, any>[] }) => {
const [echartsRef] = useEcharts(options, data);
return (
<div
ref={echartsRef}
className="h-[80%] w-[60%] absolute bottom-0 left-6"
></div>
);
};

// App.tsx
const initialPieData = [
{
value: 333,
name: "未派单",
},
{
value: 221,
name: "已派单",
},
{
value: 110,
name: "已完成",
},
];
const App = () => {
const [pieData, setPieData] = useState(initialPieData);
const changeData = () => {
setPieData((state) =>
state.map((item) => {
item.value = randomData(20, 100);
return item;
})
);
};
return <PieChart data={pieData}></PieChart>;
};

常见的配置

  1. 对于饼图而言 决定大小的是 series 对象下的 radius,与折线图和柱状图不同(当承载画布的大小确定的情况)

  2. 折线图 柱状图 距离画布的距离也就决定了图形的大小,是 option 下的 grid 中的 top left 等

1
2
3
4
5
6
grid: {
left: "3%",
right: "4%",
bottom: "3%",
containLabel: true
},
  1. 图示在图出现的位置,是在图上还是图外,可以由 series 下的 label 确定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

series: [
{
name: "value",
type: "pie",
// 饼图中radius决定大小
radius: "80%",
// 决定图示在饼图上的位置
label: {
show: true,
position: "inside",
formatter: (params: any) => {
return `${params.data.name}:${params.data.value}`;
},
color: "#fff"
},
}
]


echarts在react中的使用
https://sunburst89757.github.io/2023/01/13/echarts/
作者
Sunburst89757
发布于
2023年1月13日
许可协议