前言
在之前的文章中,我介绍过使用Three.js实现一个地球仪的旋转,在本文中我们将会介绍echarts.echarts是一款由百度开发的开源可视化图表库,它提供了各种各样的图表,可以满足各种数据展示的需求,因此echarts可以满足多种场合的使用比如:数据分析和报表,Web应用开发,移动应用等.
正文
入门使用echarts
入门使用echart,我们将会实现上述电商业务分布图,其实echart使用起来真的很简单,我们先获取echarts,获取echarts有多种方式.在案例中我们使用CDN获取
首先我们先创建一个html文件,并在在head标签中插入CDN
<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.1/dist/echarts.min.js"></script>
这样我们就可以使用echarts了.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>echarts 2D数据可视化</title>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.1/dist/echarts.min.js"></script>
</head>
<body>
<div id="main" style="width:600px;height:400px;"></div>
<script>
</script>
</body>
</html>
首先我们创建一个容器,用于展示可视化数据图表.第一步我们是要获取到容器并初始化echarts接口,使用的是echarts.init()
var myChart = echarts.init(document.getElementById('main'));
第二步就是设置数据,也称之为数据配置项
var option = {
title:{
text: '电商业务分布图'
},
tooltip:{},
legend:{//图例属性
data:['销量']
},
xAxis:{//横坐标数据
data:['衬衫','羊毛衫','雪纺衫','裤子','高跟鞋','袜子']
},
yAxis:{},//纵坐标数据
series:[{//数据
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20] //数据项
}]
}
title:使用text设置图表名称
tooltip:默认情况下,tooltip 组件用于显示当鼠标悬停在图表上的数据项时出现的提示信息。由于这里没有配置任何特定的属性,所以采用默认的提示框样式和行为.
legend:data用于定义图例的列表.
xAxis:data定义 x 轴上的类目数据,即横坐标上的标签.
yAxis:默认情况下,y 轴是一个数值轴。这里没有配置任何具体的属性,所以它会根据数据自动调整刻度和范围.
series:这是数据到图形的映射,称之系列,在系列中我们包含了我们的数据项data,type定义图表的类型,例如 'line', 'bar', 'pie', 'scatter' 等.
最后将配置项添加进入容器中即可
myChart.setOption(option).
这样我们简单实现了一个柱状图
hooks思想封装一个echarts
使用hooks封装的意义是什么呢?使用hooks封装第一点是提高了代码的复用性,第二点是降低了代码的复杂性,第三个是便于维护代码.那么相较于工具类untils,二者的区别在于什么呢?最大的区别在于hooks负责响应式的业务,而untils是纯js.
我们先使用npm init vite创建一个vue项目并在终端使用npm i echarts安装echarts,然后在src文件夹下创建一个hooks目录.第一个文件useResize.js文件.这个文件负责处理窗口尺寸变化时的事件监听和触发相关操作
import {onMounted,onUnmounted} from 'vue'
export function useResize(
handlerFn,
immediate = true
){
const handler = ()=>{
handlerFn()
}
onMounted(()=>{
window.addEventListener('resize',handler)
immediate && handler()
})
onUnmounted(()=>{
window.removeEventListener('resize',handler)
})
}
接受两个参数handlerFn一个回调函数,当窗口尺寸发生变化就会被调用,immediate表示是否在添加事件监听器后立即执行一次.
在生命周期onMounted()组件挂载完成时,就会给window添加一个resize的事件监听器,监听窗口尺寸是否发生变化,如果变化就会调用handler.immediate && handler()是在页面挂载完成就直接先执行一次,就不用等待窗口变化再调用handlerFn()了.生命周期onUnmounted()在组件卸载之后移除事件监听,以免内存泄漏.以上就是这个文件的主要功能,下面我们看到useChart.js文件
import { onUnmounted,nextTick } from "vue";
import * as echarts from 'echarts';
import {useResize} from './useResize.js'
import { throttle } from 'lodash-es';
export function useChart(
elRef
){
let chartsInstanceRef = null
let resizeFn = resize
const debounceResize = throttle(resizeFn,200)
resizeFn = debounceResize
useResize(resizeFn)
function resize(){
if(!chartsInstanceRef){
return
}
chartsInstanceRef.resize();
}
function init(){
chartsInstanceRef = echarts.init(elRef.value);
}
const setOptions = (options)=>{
init();
nextTick(()=>{
chartsInstanceRef.setOption(options)
})
}
onUnmounted(()=>{
if(!chartsInstanceRef){
return
}
chartsInstanceRef.dispose();//释放内存
chartsInstanceRef = null;//手动触发垃圾回收
})
return {
setOptions
}
}
在useChart中负责初始化echarts图表,函数接受一个elRef参数,这是一个响应式的数据,它的值会指向图表容器的DOM元素.
变量部分chartsInstanceRef用于存储echarts图表的实例引用,resizeFn一个函数用于处理窗口尺寸变化时图表的重绘,debounceResize则是通过引入lodash-es(js功能函数库)解构出throttle用于节流,这样我们就不用自己手写一个节流了.触发节流后我们就把节流处理后的函数传给useResize.js监听窗口.
我们来看看函数部分,函数resize表示如果chartsInstanceRef不存在的话,也就是没有初始化获取DOM节点,就直接返回,如果存在就会触发图表的resize方法重新计算图表的尺寸和布局.init()函数就是初始化,获取到容器的DOM节点.setOptions()配置项设置,初始化.这里nextTick()的作用是保证DOM节点是处于一个最新的状态.在生命周期onUnmounted()中,组件卸载时释放chartsInstanceRef内存,并且手动触发垃圾回收
组件PieChart
<template>
<div class="chart" ref="chartRef">
</div>
</template>
<script setup>
import {useChart} from '../hooks/useChart.js'
import {ref,onMounted} from 'vue';
const chartRef = ref(null)
const {setOptions} = useChart(chartRef)
let option
onMounted(()=>{
option = {
title:{
text:'Referer of a Website',
left:'center',
textStyle:{
color:'#fff',
fontSize:'1rem'
}
},
tooltip:{
trigger:'item',
textStyle:{
fontSize:'0.8rem'
}
},
series:[{
name: 'Access From',
type: 'pie',
radius: '50%',
data: [
{ value: 1048, name:'Search Engines' },
{ value: 735, name:'Direct' },
{ value: 580, name:'Email' },
{ value: 484, name:'Union Ads' },
{ value: 300, name:'Video Ads' },
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)',
},
},
label: {
// fontSize: '0.2rem',
color: '#fff',
fontWeight: 'bold',
}
}]
}
setOptions(option)
})
</script>
<style scoped>
.chart{
width:100%;
height:40vh;
}
</style>
最后将组件引入至App.vue中,还有一点是删除main.js中的css引入就可以了.效果展示