做大屏的时候经常会遇到 echarts 展示,下面展示在 Vue2.7 / Vue3 中对 echarts (^5.4.0) 的简单封装。

文章首发于https://blog.fxss.work/vue/echarts封装.html,样例查看

echarts 封装使用

props 说明

参数 说明 类型 可选值 默认值
opts 初始化传入的 opts https://echarts.apache.org/zh/api.html#echarts.init Object - {renderer: 'svg'}
options 配置项,对应 https://echarts.apache.org/zh/option.html#title Object - {}
seriesData series 数据配置内容https://echarts.apache.org/zh/option.html#series,数据变更自动更新 Array - []
intervalTime 自动切换的时间跨度,指自动切换 高亮 + tooltip 展示,例子 Number - 1500
autoPlay 是否自动播放,指的是是否自动添加切换 高亮 + tooltip 展示 Boolean - true
isAddOn 是否自动添加鼠标上移事件,切换 高亮 + tooltip 展示的时候,鼠标再移动到其他需要高亮显示上时,自动停止切换动画,鼠标移开自动继续播放 Boolean - true

方法

方法名 说明 参数
echartsInstance 返回 echarts 实例,如果功能不满足,自己定义 -
echartsPlay echarts开启动画,对外开放,可手动调用 clear = false, seriesIndex = 0, dataIndex = -1clear: 是否立即开始动画,并清除上个定时器,开启下个定时器,默认为 false;seriesIndex: series 中的第几项数据,默认为 0;dataIndex: series[seriesIndex].data 中的第几项,默认为 -1
echartsPause echarts关闭动画,对外开放,可手动调用 -

使用

如下演示 echarts 封装使用:

可以将如下代码拷贝到项目运行,更方便查看效果

<template><div class="overflow-y-auto bg-white text-black box-border" style="max-height: calc(100% - 80px)"><div class="flex items-start justify-between m-2"><div class="w-1/2 overflow-x-hidden border rounded-2"><h1 class="text-md my-2">1、默认展示,测试 seriesData 变更</h1><button @click="changeDate1" class="border rounded-4 py-1 px-4 hover:border-blue-700">切换</button><div class="h-80"><echarts-module :options="options1" :seriesData="seriesData1"></echarts-module></div></div><div class="w-1/2 overflow-x-hidden border rounded-2 ml-2"><h1 class="text-md my-2">2、默认不展示,展示的时候,设置 seriesData</h1><button @click="changeDate2" class="border rounded-4 py-1 px-4 hover:border-blue-700">切换</button><div class="h-80"><echarts-module v-if="isShow" :options="options2" :seriesData="seriesData2"></echarts-module></div></div></div><div class="flex items-start justify-between m-2"><div class="w-1/2 overflow-x-hidden border rounded-2"><h1 class="text-md my-2">3、前后两次赋值的 seriesData[0].data.length 不一样,动画从头开始</h1><button @click="changeDate3" class="border rounded-4 py-1 px-4 hover:border-blue-700">切换</button><div class="h-80"><echarts-module :options="options3" :seriesData="seriesData3"></echarts-module></div></div><div class="w-1/2 overflow-x-hidden border rounded-2 ml-2"><h1 class="text-md my-2">4、切换宽高,自动 resize</h1><button @click="changeDate4" class="border rounded-4 py-1 px-4 hover:border-blue-700">切换宽度</button><button @click="changeDate41" class="border rounded-4 py-1 px-4 ml-3 hover:border-blue-700">切换高度</button><div class="h-80"><div :style="{ width: boxWidth4 ? '100%' : '50%', height: boxHeight4 ? '100%' : '75%' }"><echarts-module :options="options4" :seriesData="seriesData4"></echarts-module></div></div></div></div><div class="flex items-start justify-between m-2"><div class="w-1/2 overflow-x-hidden border rounded-2"><h1 class="text-md my-2">5、通过 ref 调用开始结束动画,使用 ref 调用的好处是可以指定在第几项开始动画</h1><button @click="changeDate5" class="border rounded-4 py-1 px-4 hover:border-blue-700">开始动画</button><button @click="changeDate51" class="border rounded-4 py-1 px-4 ml-3 hover:border-blue-700">关闭动画</button><div class="h-80"><echarts-module ref="echartsModule5" :options="options5" :seriesData="seriesData5" :autoPlay="false"></echarts-module></div></div><div class="w-1/2 overflow-x-hidden border rounded-2 ml-2"><h1 class="text-md my-2">6、改变 autoPlay 开始结束动画,使用 autoPlay 改变的好处是可以从上次暂停动画项处继续动画</h1><button @click="changeDate6" class="border rounded-4 py-1 px-4 hover:border-blue-700">{{ autoPlay6 ? '结束' : '开始' }}动画</button><div class="h-80"><echarts-module ref="echartsModule6" :options="options6" :seriesData="seriesData6" :autoPlay="autoPlay6"></echarts-module></div></div></div><div class="flex items-start justify-between m-2"><div class="w-1/2 overflow-x-hidden border rounded-2"><h1 class="text-md my-2">7、切换动画跳动时间 5s -> 1s</h1><button @click="changeDate7" class="border rounded-4 py-1 px-4 hover:border-blue-700">切换</button><div class="h-80"><echarts-module :options="options7" :seriesData="seriesData7" :intervalTime="timeout"></echarts-module></div></div><div class="w-1/2 overflow-x-hidden border rounded-2 ml-2"><h1 class="text-md my-2">8、通过 isAddOn 添加移除鼠标事件</h1><button @click="changeDate8" class="border rounded-4 py-1 px-4 hover:border-blue-700">{{ isAddOn8 ? '移除' : '添加' }}</button><div class="h-80"><echarts-module :options="options8" :seriesData="seriesData8" :isAddOn="isAddOn8"></echarts-module></div></div></div></div>
</template><script setup>import { ref, reactive, nextTick } from 'vue'import EchartsModule from './../components/EchartsModule.vue'// 图表1const options1 = reactive({legend: {},xAxis: {type: 'category',data: ['Matcha Latte', 'Milk Tea', 'Cheese Cocoa', 'Walnut Brownie', 'Brownie', 'Cheese']},yAxis: {},tooltip: {trigger: 'axis'}})const seriesData1 = ref([{type: 'bar',name: '2015',data: [89.3, 92.1, 94.4, 85.4, 88, 90]},{type: 'bar',name: '2016',data: [95.8, 89.4, 91.2, 76.9, 75, 68]},{type: 'bar',name: '2017',data: [97.7, 83.1, 92.5, 78.1, 95, 93]}])function changeDate1() {seriesData1.value = [{type: 'bar',name: '2015',data: [89.3, 92.1, 94.4, 85.4, 50, 69]},{type: 'bar',name: '2016',data: [95.8, 89.4, 91.2, 76.9, 75, 68]}]}// 图表2const isShow = ref(false)const options2 = reactive({legend: {},xAxis: {},yAxis: {type: 'category',data: ['Latte', 'Tea', 'Cocoa', 'Brownie']},tooltip: {trigger: 'axis'}})const seriesData2 = ref([])function changeDate2() {isShow.value = trueseriesData2.value = [{type: 'bar',name: '2015',data: [89.3, 92.1, 94.4, 85.4]},{type: 'bar',name: '2016',data: [95.8, 89.4, 91.2, 76.9]}]}// 图表3const options3 = reactive({legend: {},xAxis: {type: 'category',data: ['Matcha Latte', 'Milk Tea', 'Cheese Cocoa', 'Walnut Brownie', 'Brownie', 'Cheese']},yAxis: {},tooltip: {trigger: 'axis'}})const seriesData3 = ref([{type: 'bar',name: '2015',data: [89.3, 92.1, 94.4, 85.4, 88, 90]},{type: 'bar',name: '2016',data: [95.8, 89.4, 91.2, 76.9, 75, 68]},{type: 'bar',name: '2017',data: [97.7, 83.1, 92.5, 78.1, 95, 93]}])function changeDate3() {seriesData3.value = [{type: 'bar',name: '2015',data: [89.3, 92.1]}]}// 图表4const boxWidth4 = ref(true)const boxHeight4 = ref(true)const options4 = reactive({legend: {},xAxis: {type: 'category',data: ['Matcha Latte', 'Milk Tea', 'Cheese Cocoa', 'Walnut Brownie', 'Brownie', 'Cheese']},yAxis: {},tooltip: {trigger: 'axis'}})const seriesData4 = ref([{type: 'line',name: '2015',data: [89.3, 92.1, 94.4, 85.4, 88, 90]},{type: 'line',name: '2016',data: [95.8, 89.4, 91.2, 76.9, 75, 68]},{type: 'line',name: '2017',data: [97.7, 83.1, 92.5, 78.1, 95, 93]}])function changeDate4() {boxWidth4.value = !boxWidth4.value}function changeDate41() {boxHeight4.value = !boxHeight4.value}// 图表5const options5 = reactive({title: {text: '饼图程序调用高亮示例',left: 'center'},tooltip: {trigger: 'item',formatter: '{a} <br/>{b} : {c} ({d}%)',confine: true},legend: {orient: 'vertical',left: 'left',data: ['直接访问', '邮件营销', '联盟广告', '视频广告', '搜索引擎']}})const seriesData5 = ref([{name: '访问来源',type: 'pie',radius: '55%',center: ['50%', '60%'],data: [{ value: 335, name: '直接访问' },{ value: 310, name: '邮件营销' },{ value: 234, name: '联盟广告' },{ value: 135, name: '视频广告' },{ value: 1548, name: '搜索引擎' }],emphasis: {itemStyle: {shadowBlur: 10,shadowOffsetX: 0,shadowColor: 'rgba(0, 0, 0, 0.5)'}}}])const echartsModule5 = ref()function changeDate5() {echartsModule5.value.echartsPlay(true, 0, -1)}function changeDate51() {echartsModule5.value.echartsPause()}// 图表6const autoPlay6 = ref(false)const options6 = reactive({title: {text: '饼图程序调用高亮示例',left: 'center'},tooltip: {trigger: 'item',formatter: '{a} <br/>{b} : {c} ({d}%)',confine: true},legend: {orient: 'vertical',left: 'left',data: ['直接访问', '邮件营销', '联盟广告', '视频广告', '搜索引擎']}})const seriesData6 = ref([{name: '访问来源',type: 'pie',radius: '55%',center: ['50%', '60%'],data: [{ value: 335, name: '直接访问' },{ value: 310, name: '邮件营销' },{ value: 234, name: '联盟广告' },{ value: 135, name: '视频广告' },{ value: 1548, name: '搜索引擎' }],emphasis: {itemStyle: {shadowBlur: 10,shadowOffsetX: 0,shadowColor: 'rgba(0, 0, 0, 0.5)'}}}])const echartsModule6 = ref()function changeDate6() {autoPlay6.value = !autoPlay6.value}// 图表7const timeout = ref(5000)const options7 = reactive({legend: {},xAxis: {type: 'category',data: ['Matcha Latte', 'Milk Tea', 'Cheese Cocoa', 'Walnut Brownie', 'Brownie', 'Cheese']},yAxis: {},tooltip: {trigger: 'axis'}})const seriesData7 = ref([{type: 'line',name: '2015',data: [89.3, 92.1, 94.4, 85.4, 88, 90]},{type: 'line',name: '2016',data: [95.8, 89.4, 91.2, 76.9, 75, 68]},{type: 'line',name: '2017',data: [97.7, 83.1, 92.5, 78.1, 95, 93]}])function changeDate7() {timeout.value = 1000}// 图表8const isAddOn8 = ref(false)const options8 = reactive({legend: {},xAxis: {type: 'category',data: ['Matcha Latte', 'Milk Tea', 'Cheese Cocoa', 'Walnut Brownie', 'Brownie', 'Cheese']},yAxis: {},tooltip: {trigger: 'axis'}})const seriesData8 = ref([{type: 'line',name: '2015',data: [89.3, 92.1, 94.4, 85.4, 88, 90]},{type: 'line',name: '2016',data: [95.8, 89.4, 91.2, 76.9, 75, 68]},{type: 'line',name: '2017',data: [97.7, 83.1, 92.5, 78.1, 95, 93]}])function changeDate8() {isAddOn8.value = !isAddOn8.value}
</script>

代码封装

<template><div ref="echartsRef" style="width: 100%; height: 100%"></div>
</template><script setup>import { defineProps, defineExpose, watch, nextTick, ref, onMounted, onBeforeUnmount } from 'vue'import * as echarts from 'echarts'import { useElementSize } from '@vueuse/core'const props = defineProps({// https://echarts.apache.org/zh/api.html#echarts.init// 初始化传入的 optsopts: {type: Object,default() {return {renderer: 'svg'}}},// 配置项options: {type: Object,default() {return {}}},// 数据集合seriesData: {type: Array,default() {return []}},// 自动切换的时间跨度intervalTime: {type: Number,default: 1500},// 是否自动播放autoPlay: {type: Boolean,default: true},// 是否自动添加鼠标上移事件isAddOn: {type: Boolean,default: true}})const echartsRef = ref()let myChart = nulllet echartsOptions = {}let myChartEventTime = nulllet currentSeriesIndex = 0let currentDataIndex = -1// 是否调用过 echartsPlaylet isEchartsPlay = false// echarts初始化function init() {destroyEchart() //判断是否有echart实例,如果有,先销毁myChart = echarts.init(echartsRef.value, null, props.opts)update()if (props.isAddOn) {addEventFn()}}// 绑定事件function addEventFn() {// 鼠标移上查看的时候,暂停动画myChart.on('mouseover', 'series', event => {// 取消之前高亮的图形myChart.dispatchAction({type: 'downplay',seriesIndex: currentSeriesIndex,dataIndex: currentDataIndex})echartsPause()})// 鼠标移出的时候打开动画myChart.on('mouseout', 'series', event => {// 自动播放 或者 调用过 echartsPlayif (props.autoPlay || isEchartsPlay) echartsPlay(true, event.seriesIndex, event.dataIndex - 1)})}// 移除事件function removeEventFn() {myChart.off('mouseover')myChart.off('mouseout')}// 数据更新function update(isRefresh = false) {// 逻辑处理组件options参数const options = {...props.options,series: props.seriesData// other options here ...}echartsOptions = options// 调用ECharts组件setOption更新nextTick(() => {myChart.setOption(options, true)if (options.series.length && props.autoPlay) {if (isRefresh) {echartsPlay(false, currentSeriesIndex, -1)} else {echartsPlay(false, currentSeriesIndex, currentDataIndex)}}})}// 销毁echartsfunction destroyEchart() {if (myChart) {if (props.isAddOn) {removeEventFn()}if (typeof myChart.clear === 'function') myChart.clear()if (typeof myChart.dispose === 'function') myChart.dispose()myChart = null}}/*** echarts开启动画,对外开放,可手动调用* clear: 是否立即开始动画,并清除上个定时器,开启下个定时器,默认为 false* seriesIndex: series 中的第几项数据,默认为 0* dataIndex: series[seriesIndex].data 中的第几项,默认为 -1*/function echartsPlay(clear = false, seriesIndex = 0, dataIndex = -1) {if (clear) {echartsPause()}isEchartsPlay = truecurrentSeriesIndex = seriesIndexcurrentDataIndex = dataIndexif (!myChartEventTime) {echartsEventPlay(seriesIndex)}}function echartsTimeout(seriesIndex = 0) {myChartEventTime = setTimeout(() => {echartsEventPlay(seriesIndex)}, props.intervalTime)}function echartsEventPlay(seriesIndex = 0) {const dataLen = echartsOptions.series[seriesIndex].data.lengthif (myChart && myChart.dispatchAction) {// 取消之前高亮的图形myChart.dispatchAction({type: 'downplay',seriesIndex,dataIndex: currentDataIndex})currentDataIndex = (currentDataIndex + 1) % dataLen// 高亮当前图形myChart.dispatchAction({type: 'highlight',seriesIndex,dataIndex: currentDataIndex})// 显示 tooltipmyChart.dispatchAction({type: 'showTip',seriesIndex,dataIndex: currentDataIndex})}echartsTimeout(seriesIndex)}// echarts关闭动画,对外开放,可手动调用function echartsPause() {if (myChart && myChart.dispatchAction) {// 取消之前高亮的图形myChart.dispatchAction({type: 'downplay',seriesIndex: currentSeriesIndex,dataIndex: currentDataIndex})// 取消显示 tooltipmyChart.dispatchAction({type: 'hideTip'})}if (myChartEventTime) {clearTimeout(myChartEventTime)myChartEventTime = null}}// 重置大小function echartsResize() {if (myChart) myChart.resize()}onMounted(() => {init()})onBeforeUnmount(() => {echartsPause()destroyEchart()})watch(() => props.seriesData,(val, oldVal) => {let isRefresh = false// 前后两次赋值的 seriesData[0].data.length 不一样,动画从头开始if (val.length > 0 && val[currentSeriesIndex].data && oldVal.length > 0 && oldVal[currentSeriesIndex].data && val[currentSeriesIndex].data.length !== oldVal[currentSeriesIndex].data.length) {isRefresh = true}update(isRefresh)},{ deep: true })// 监听 props.autoPlay ,自动关闭、继续动画watch(() => props.autoPlay,val => {if (val) {echartsPlay(false, currentSeriesIndex, currentDataIndex)} else {echartsPause()}})// 监听 props.isAddOn ,自动添加、移除事件watch(() => props.isAddOn,val => {if (val) {addEventFn()} else {removeEventFn()}})// 父元素大小改变的时候,自动 resiezeconst { width, height } = useElementSize(echartsRef)watch(() => width.value,val => {nextTick(() => {echartsResize()})})watch(() => height.value,val => {nextTick(() => {echartsResize()})})defineExpose({echartsInstance: () => myChart,echartsPlay,echartsPause})
</script>

Vue echarts封装相关推荐

  1. vue+echarts封装日历图

    前端可视化封装日历图 html <template><divref="calendar":style="{ width: `${width}px`, h ...

  2. echarts vue组件封装

    echarts vue组件封装 为什么封装echarts组件 1.原生echarts不是vue组件风格的,不爽 2.原生echarts需要操作dom,麻烦 3.原生echarts没有响应式系统,太菜 ...

  3. vue+echarts的组件封装

    本文是把echarts封装成一个公共组件,方便调用, 首先:先给echarts设置一个canvas画布,也就是俗称的div盒子 其次:下载echarts依赖,然后引入,如果报错的话就按照下面这种方式引 ...

  4. 三维交互可视化平台(智慧海上牧场平台)学习开发Flask+Vue+Echarts+Mysql+websocket 实战(四)

    前言 三维交互可视化平台(智慧海上牧场平台)学习开发之Vue(一) 三维交互可视化平台(智慧海上牧场平台)学习开发之Flask+Vue+Mysql(二) 三维交互可视化平台(智慧海上牧场平台)学习开发 ...

  5. Echarts 双柱状图+折线图合并---实现效果详解(vue+Echarts实现)

    此文章讲解 Echarts 在 vue 开发中的使用方式以及实现效果的 demo 示例展示; 如有疑问或者不清楚的欢迎随时提问 . 废话不多说, 直接上代码以及图例 (为了让大家方便阅读, 都有自己验 ...

  6. 「干货」用 Vue + Echarts 打造你的专属可视化界面(上)

    作者简介: Jaked  8年前端工作经验, 主要分享:职业发展方面.前端技术.面试技巧等. 公众号:超哥前端小栈 掘金:https://juejin.im/user/5a5d452251882573 ...

  7. 记录一次 Vue 组件封装过程

    引言 开发前端项目过程中,有大量的图表数据需要展示,为了更方便地使用以及代码的复用,于是基于ECharts封装了各种各样的图表组件.直接使用封装好的组件对于刚接触我们项目的人来说会比较友好,而理解组件 ...

  8. Vue+Echarts构建可视化大数据平台实战项目(上)粒子动效,登录界面抖动,背景图轮播★

    Vue+Echarts构建可视化大数据平台实战项目(上) 前言 分享之前我们先来普及一下什么是数据可视化?数据可视化可以把数据从冰冷的数字转换成图形,揭示蕴含在数据中的规律和道理.数据可视化通俗来说就 ...

  9. echarts vue 酷炫图_「干货」用 Vue + Echarts 打造你的专属可视化界面(上)

    作者简介: Jaked 8年前端工作经验, 主要分享:职业发展方面.前端技术.面试技巧等. 在近期的项目中,有大量处理可视化数据的需求.说起这个,相信很多同学跟我一样,都会想到用 Echarts 来实 ...

最新文章

  1. 我的Pandas学习经历及动手实践
  2. Servlet3.0之二:异步特性
  3. aho-corasick php,GitHub - coralh/php-akm: Ahocorasick keyword match. Supports php7 and php5
  4. 再见了Dubbo!正式拥抱下一个神级Java开发框架!
  5. 分布式服务器集群架构方案思考
  6. 实现一个登录:Mac+.NET 5+Identity+JWT+VS Code
  7. 【MySQL 】学习笔记千行总结
  8. 江苏高中计算机考试成绩查询系统,江苏2018普通高中信息技术学业水平测试成绩查询系统已开通...
  9. FIN7 正在转向密码重置和软件供应链攻击
  10. 低光照图像增强论文Low-Light Image Enhancement with Normalizing Flow阅读笔记
  11. Devfreq Bus Dcvs
  12. mac录屏快捷键 - mac截图截屏快捷键 - 自带录屏软件QuickTime Player如何使用
  13. android仿微信、QQ等聊天界面,实现点击输入框弹出软键盘、点击其他区域收起软键盘,默认滑动至最低端
  14. 电音(4)House类电音
  15. 系统 应用程序 提示 初始化失败 或 无法加载模块 等错误
  16. 利用VirtualBox搭建私有云
  17. php+供应商管理系统,供应商管理系统
  18. 谈我们为什么学不好编程2——你是否已进入“等死模式”?
  19. js进阶之你必须要会的技术!
  20. 统计学计算机数据输入,EpiData:科研数据录入与管理的必备神器

热门文章

  1. Linux平台代码覆盖率测试工具GCOV的前端工具LCOV简介
  2. MySQL系统学习笔记
  3. Dynamics CRM 之ADFS 使用 WID 的独立联合服务器
  4. vooc充电原理_OPPO VOOC充电技术详解
  5. 霜波:她是双11的大队长,她也是天猫资深美女程序媛
  6. VS2010/MFC编程入门教程
  7. 中国无车承运人行业需求前景与投资战略研究报告2022-2027年
  8. signature=91a39d56ee3f1c2eb35c4ca5adda65a1,Anomalous signature splitting effects in 79Rb
  9. uni-app视频播放及下载功能
  10. 第二章 大数据技术概述