echarts 2D数据可视化 + hooks 新手入门

629 阅读5分钟

前言

    在之前的文章中,我介绍过使用Three.js实现一个地球仪的旋转,在本文中我们将会介绍echarts.echarts是一款由百度开发的开源可视化图表库,它提供了各种各样的图表,可以满足各种数据展示的需求,因此echarts可以满足多种场合的使用比如:数据分析和报表,Web应用开发,移动应用等.

正文

入门使用echarts

image.png

入门使用echart,我们将会实现上述电商业务分布图,其实echart使用起来真的很简单,我们先获取echarts,获取echarts有多种方式.在案例中我们使用CDN获取

image.png

首先我们先创建一个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引入就可以了.效果展示

FEE658BA3106AF6B184E1F2F71ACEBD7.gif