引言
在项目的开发中,对于我们前端开发人员而言,总是无法避免需要对数据进行可视化分析和设计的需求。但事实上,如果单纯的依靠Html5 Canvas想要快速地创建简洁,美观,炫酷的可视化作品难度极大且可维护性差。而现如今随着技术的迭代更新发展,已经出现很多可靠,易用,操作便捷,可交互,跨平台的一些可视化解决方案如ECharts,HighCharts,,Chart.js等。于是在本文中,我们以ECharts为例,来尝试将可视化解决方案应用于React-当前最流行的前端框架之一。 因为React的性能优越,灵活性高,而ECharts 的实用性和性能相比于其他竞品都要略胜一筹,所以这两种技术栈的使用需求还是比较旺盛,将Echarts应用到React项目中的场景也比较常见。
一、开发前准备
如果在原生的JS应用或者jQuery项目中,我们常用的方式就是直接去官网下载其核心js文件并导入我们的项目中使用,但是在React项目中,我们大可不必,由于React项目开发基于webpack做了二次封装,而webpack又是基于 Node.js的前端项目部署打包工具,总而言之,React项目开发是在nodejs环境基础上,所以可以直接利用npm包管理器将第三方工具模块下载加入到项目中,并通过import引入对应的模块到相关页面中使用,不需要关心其中的细节。
具体操作流程
1.下载安装Echarts到项目中,通过npm/yarn包管理器:
npm i -S echarts / yarn add echarts (注意需要安装到生产依赖)
2.将ECharts引入编写的react组件中并使用的范式:
import React, {
Component
} from "react";
// 引入ECharts主模块
import * as echarts from "echarts/lib/echarts";
//按需引入需要的Echart模块
...
class APP extends Component {
componentDidMount() {
// 初始化echarts实例,将其挂载到id为main的dom元素上展示
var myChart = echarts.init(document.getElementById("main"));
// 绘制图表
myChart.setOption({
...
});
}
render() { //渲染需要陈放Echart实例的容器元素
return <div id = "main"
style = {
{
width: 400,
height: 400
}
} > < /div>;
}
}
export default APP;
二、案例
1、通过极坐标双数值轴绘制爱心
最终实现效果
思路分析
1.创建一个React组件,并且需要组件内的状态state,render函数,componentDidMount钩子
2.render函数渲染需要容纳Echart实例的容器元素,并需要声明id,方便Echarts实例找到挂载的目标
3.设置组件内的状态state,定义sourceData存放Echarts实例的数据源
3.componentDidMount钩子,当render函数渲染完容器元素之后调用,主要作用如下:
1)生成坐标数据源,并更新到state中的sourceData上
2)初始化Echarts实例,将其挂载到id为main的div元素上
3)通过myChart.setOption(obj)将需要展示的数据,整合成一个obj对象包括sourceData,绘制爱心图形
demo源码
import React, { Component} from "react";
// 引入ECharts主模块
import * as echarts from "echarts/lib/echarts";
// 引入折线图需要的模块
import "echarts/lib/chart/line";
import "echarts/lib/component/title";
import "echarts/lib/component/tooltip";
import "echarts/lib/component/legend";
import 'echarts/lib/component/polar';
class App extends Component { // 初始化状态
state = {
sourceData: [],
};
async componentDidMount() {
let data = [];
for (let i = 0; i <= 100; i++) {//根据公式,生成绘制在图上的坐标数据源数组
let theta = i / 100 * 360;
let r = 5 * (1 + Math.sin(theta / 180 * Math.PI));
data.push([r, theta]);
}
this.setState(() => {
return {
sourceData: data//更新react组件的state数据
};
});
// 初始化Echarts实例,将其挂载到id为main的dom元素上展示
let myChart = echarts.init(document.getElementById("main"));
// 绘制Echarts实例所需要的数据
myChart.setOption({
title: {
text: '极坐标双数值轴'
},
legend: {
data: ['line']
},
polar: {},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
},
angleAxis: {
type: 'value',
startAngle: 0
},
radiusAxis: {
},
series: [{
coordinateSystem: 'polar',//极坐标图
name: 'line',
type: 'line',
data: data //根据已生成的坐标数组来绘制爱心图形
}]
}
);
}
render() {//渲染需要陈放Echart实例的容器元素
return <div id = "main" style = { { width: 1000, height: 600 }}> </div>;
}
}
export default App;
1.创建一个React组件,并且需要组件内的状态state,render函数,componentDidMount钩子
2.render函数渲染需要容纳Echart实例的容器元素,并需要声明id,方便Echarts实例找到挂载的目标
3.设置组件内的状态state,定义sourceData存放Echarts实例的数据源
3.componentDidMount钩子,当render函数渲染完容器元素之后调用,主要作用如下:
1)初始化Echarts实例,将其挂载到id为main的div元素上
2)通过myChart.setOption(obj)将需要展示的数据包括state的数据data,celldata,整合成一个obj对象,并绘制图表。
demo源码
import React, {
Component
} from "react";
// 引入ECharts主模块
import * as echarts from "echarts/lib/echarts";
// 引入饼状图需要的模块
import "echarts/lib/chart/pie";
import "echarts/lib/component/title";
import "echarts/lib/component/tooltip";
import "echarts/lib/component/legend";
class App extends Component { // 初始化状态
state = {
data: [
{value: 150, name: '语文'},
{value: 110, name: '物理'},
{value: 150, name: '数学'},
{value: 100, name: '化学'},
{value: 150, name: '英语'},
{value: 90, name: '生物'},
],
celldata:['语文', '物理', '数学', '化学', '英语', '生物']
};
async componentDidMount() {
var myChart = echarts.init(document.getElementById("main"));
myChart.setOption(
{
title: {
text: '高考理科分数占比',
left: 'center'
},
tooltip: {
trigger: 'item',
formatter: '{a}
{b} : {c} ({d}%)'
},
legend: {
left: 'center',
top: 'bottom',
data: this.state.celldata
},
toolbox: {
show: true,
feature: {
mark: {show: true},
dataView: {show: true, readOnly: false},
magicType: {
show: true,
type: ['pie', 'funnel']
},
restore: {show: true},
saveAsImage: {show: true}
}
},
series: [
{
name: '分数',
type: 'pie',
radius: [30, 110],
center: ['50%', '50%'],
roseType: 'area',
data: this.state.data
}
]
}
);
}
render() {
return <div id = "main" style = { { width: 1000, height: 400 }}> </div>;
}
}
export default App;