在 React 项目中使用 ECharts
说明
重要文件版本
- “react”: “^16.2.0”
- “echarts”: “^4.0.2”
- “redux”: “^3.7.2”,
- “react-router-dom”: “^4.2.2”
- “react-router-redux”: “^5.0.0-alpha.9”
- “react-hot-loader”: “^4.0.0-beta.21”
在 React 项目中使用 ECharts 生成图表,与使用其他第三方库没有太大的区别,只要在 React 的组件
componentDidMount
声明周期中初始化 ECharts 图表,然后在每次更新组件时调用 ECharts 实例的setOption()
方法更新配置即可,以下记录了使用当中的一些细节
编写 <Chart/>
图表组件
>
/*
* ECharts 组件基础部分
* */
import React, { PureComponent } from 'react';
import * as echarts from 'echarts';
import 'zrender/lib/svg/svg';
import throttle from '../../utils/throttle'; // 一个节流函数
export default class Chart extends PureComponent {
constructor(props) {
super(props);
this.state = {
width: '100%',
height: '100%'
};
this.chart = null;
}
/*
注意:
虽然在 componentDidMount 中组件已经被装配,
但是如果设置容器宽高为百分比的值,那么容器的 clientWidth 和 clientHeight 有可能还处于计算中
这个时候如果在容器中实例化 echarts,echarts 获得的 clientWidth 和 clientHeight 不一定是我们预期的,
因此这里使用了定时器延迟实例化,也可以提前计算出像素之后 赋值给 width、height,这样不是百分比就没有问题
*/
async componentDidMount() {
console.log('did mount');
// 初始化图表
await this.initChart(this.el);
// 将传入的配置(包含数据)注入
this.setOption(this.props.option);
// 监听屏幕缩放,重新绘制 echart 图表
window.addEventListener('resize', throttle(this.resize, 100));
}
componentDidUpdate() {
// 每次更新组件都重置
this.setOption(this.props.option);
}
componentWillUnmount() {
// 组件卸载前卸载图表
this.dispose();
}
render() {
const { width, height } = this.state;
return (
<div
className="default-chart"
ref={el => (this.el = el)}
style={{ width, height }}
/>
);
}
initChart = el => {
// renderer 用于配置渲染方式 可以是 svg 或者 canvas
const renderer = this.props.renderer || 'canvas';
console.log(renderer);
return new Promise(resolve => {
setTimeout(() => {
this.chart = echarts.init(el, null, {
renderer,
width: 'auto',
height: 'auto'
});
resolve();
}, 0);
});
};
setOption = option => {
if (!this.chart) {
return;
}
const notMerge = this.props.notMerge;
const lazyUpdate = this.props.lazyUpdate;
this.chart.setOption(option, notMerge, lazyUpdate);
};
dispose = () => {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
};
resize = () => {
this.chart && this.chart.resize();
};
getInstance = () => {
return this.chart;
};
}
其他组件中引用图表组件
/*
Heatmap 热力图
*/
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/title';
import 'echarts/lib/component/grid';
import 'echarts/lib/chart/heatmap';
import 'echarts/lib/component/visualMap';
import Chart from '../components/Chart/index';
import { getChart } from '../modules/charts/actions';
class HeatmapChart extends Component {
constructor(props) {
super(props);
this.state = {
renderer: 'canvas'
};
}
async componentWillMount() {
// 装载前 获取数据
const path = '/heatmap';
const key = 'heatmap';
await this.props.getChart({ path, key });
}
render() {
const renderer = this.state.renderer;
const option = this.getOption();
return <Chart renderer={renderer} option={option} />;
}
// getOption 这个函数主要用于配置 option,包括将数据配置进去
// 也可以将其放在 state 中,然后通过 setState 更新
getOption = () => {
// 组装数据,返回配置 option
const currentData = this.props.charts.heatmap;
return {
tooltip: {
position: 'top'
},
grid: {
containLabel: true
},
xAxis: {
type: 'category',
splitArea: {
show: true
},
boundaryGap: true
},
yAxis: {
type: 'category',
splitArea: {
show: true
},
boundaryGap: true
},
visualMap: {
min: 0,
max: 20,
calculable: true,
left: 'left',
bottom: 'bottom',
dimension: 2
},
dataset: {
source: currentData
},
series: [
{
name: '热力图',
type: 'heatmap',
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
},
encode: {
x: 0,
y: 1
},
tooltip: {
formatter(params) {
const [x, y, value] = params.data;
return [
`x: ${x}`,
`y: ${y}`,
`value: ${value}`
].join('<br/>');
}
}
}
]
};
};
}
export default connect(
state => ({ charts: state.charts }),
dispatch => ({
getChart: bindActionCreators(getChart, dispatch)
})
)(HeatmapChart);