echarts轮播

96 阅读4分钟

注:轮播库支持的echarts版本需大于5.0.0,低于该版本的库,会出现异常,案例的echarts版本为5.2.1

核心类

 /**
  * 创建时间:2023-07-11 11:30:46
  * 作者:Ayo
  * !模块名:ecahrts轮播
  * 描述:
  *
  * 参数说明
  * @echartsDom {DOM} ecahrts挂载的dom节点
  * @echartsTarget {Ecahrts Obj} ecahrts对象
  * @chartOption {Object} ecahrts对象
  * @timer {timer} 计时器对象
  * @dataLength {number} 数据长度,用于判断数据轮播的最终位置
  * @step {time} 计时器执行速度,默认3000
  * @targetIndex {Number} 目标开始轮询的索引,默认0或者上次索引
  *
  *
  * 返回值
  * @ecahrtsTooltipPaly:{ecahrtsTooltipPaly} ecahrtsTooltipPaly的class对象
  */
 (function (global, factory) {
     if (typeof exports === 'object' && typeof module !== 'undefined') {
         module.exports = factory();
     } else if (typeof define === 'function' && define.amd) {
         define(factory);
     } else {
         (global = global || self), (global.ecahrtsTooltipPaly = factory());
     }
 })(this, function () {
     class ecahrtsTooltipPaly {
         constructor(echartsDom, echartsTarget, chartOption, timer, dataLength, step, targetIndex) {
             if (typeof echartsDom === 'undefined') {
                 throw new Error('必须传入echarts的DOM节点');
             }
             if (typeof echartsTarget === 'undefined') {
                 throw new Error('必须传入echarts对象');
             }
             if (typeof chartOption === 'undefined') {
                 throw new Error('必须传入echarts的option对象');
             }
             this.echartsDom = echartsDom;
             this.echartsTarget = echartsTarget;
             this.chartOption = chartOption;
             this.dataLength = dataLength;
             this.timer = timer;
             this.step = step || 3000;
             this.targetIndex = targetIndex || -1;
 ​
             this.init();
         }
 ​
         /* 初始化 */
         init() {
             if (!this.echartsTarget) {
                 return;
             }
             this.play();
             //dom的移入移出事件
             this.openDomMonitor();
             //ecahrts的移入
             // this.openEchartsMonitor();
         }
 ​
         /* 开启ecahrts移入事件的监听  => 和开启dom事件不冲突,可能存在图例不是ecahrts绘制的,是通过div实现的 */
         openEchartsMonitor() {
             if (!this.echartsTarget) {
                 return;
             }
             let that = this;
             this.echartsTarget.on('mouseover', function (params) {
                 that.setPlayIndex(params.dataIndex - 1);
             });
         }
 ​
         /* 关闭ecahrts移入事件的监听 */
         colseEchartsMonitor() {
             if (!this.echartsTarget) {
                 return;
             }
             this.echartsTarget.off('mouseover');
         }
 ​
         /* 开启轮询 */
         play() {
             if (!this.echartsTarget) {
                 return;
             }
 ​
             this.timer && clearInterval(this.timer); //清除定时器,防止轮播出现混乱
 ​
             this.dataLength =
                 this.dataLength ||
                 this.chartOption?.series?.data?.length ||
                 this.chartOption?.series[0]?.data?.length; //计算索引
 ​
             let dataZoomExit = false;
 ​
             var maxValueSpan = 5;
 ​
             //验证dataZoom是否存在,如果存在则开启dataZoom滚动
             if (this.chartOption.dataZoom) {
                 maxValueSpan = this.chartOption.dataZoom[0].maxValueSpan;
                 dataZoomExit = true;
             }
 ​
             let that = this;
 ​
             this.timer = setInterval(function () {
                 that.echartsTarget.dispatchAction({
                     type: 'downplay',
                     seriesIndex: 0,
                     dataIndex: that.targetIndex,
                 });
 ​
                 that.targetIndex = (that.targetIndex + 1) % that.dataLength;
 ​
                 that.echartsTarget.dispatchAction({
                     type: 'highlight',
                     seriesIndex: 0,
                     dataIndex: that.targetIndex,
                 });
 ​
                 that.echartsTarget.dispatchAction({
                     //Echarts提供的方法
                     type: 'showTip',
                     seriesIndex: 0,
                     dataIndex: that.targetIndex,
                 });
 ​
                 if (dataZoomExit) {
                     that.echartsTarget.dispatchAction({
                         type: 'dataZoom',
                         startValue: that.targetIndex,
                         endValue: that.targetIndex + maxValueSpan,
                     });
 ​
                     // 监听 dataZoom 更新事件 => 开启轮播后,tooltip显示数据异常
                     that.echartsTarget.off('dataZoom'); // 先取消之前的监听,以免重复绑定
                     that.echartsTarget.on('dataZoom', function (params) {
                         // 使用 dispatchAction 方法手动刷新 tooltip
                         that.echartsTarget.dispatchAction({
                             type: 'showTip',
                             seriesIndex: 0,
                             // dataIndex: Math.floor(params.startValue), // 或者使用 endIndex
                             dataIndex: that.targetIndex,
                         });
                     });
                 }
             }, this.step); //每隔3秒轮播一次
         }
 ​
         /* 暂停轮询 */
         stop() {
             if (!this.echartsTarget) {
                 return;
             }
             this.timer && clearInterval(this.timer);
             this.echartsTarget.dispatchAction({
                 type: 'downplay',
                 seriesIndex: 0,
                 dataIndex: this.targetIndex,
             });
             // this.setPlayIndex(this.targetIndex);
         }
 ​
         /* 验证dom是否存在鼠标移入移出的监听 */
         verifyDomMonitor() {
             if (!this.echartsTarget) {
                 return;
             }
             if (typeof this.monitorOver == 'function' || typeof this.monitorOut == 'function') {
                 return true;
             } else {
                 return false;
             }
         }
 ​
         /* 开启鼠标移入移出的监听 */
         openDomMonitor() {
             if (!this.echartsTarget) {
                 return;
             }
             if (this.verifyDomMonitor()) {
                 console.error('已存在的dom监听事件,不可重复添加');
                 return;
             }
 ​
             //为了满足移出监听事件的要求,必须保证堆栈信息一致
             this.monitorOver = () => {
                 this.stop();
             };
 ​
             this.monitorOut = () => {
                 this.play();
             };
 ​
             //开启鼠标移入移出事件
             this.echartsDom.addEventListener('mouseover', this.monitorOver);
             this.echartsDom.addEventListener('mouseout', this.monitorOut);
         }
 ​
         closeDomMonitor() {
             if (!this.echartsTarget) {
                 return;
             }
             if (!this.verifyDomMonitor()) {
                 console.warn('将要的移出dom监听事件不存在');
                 return;
             }
             this.echartsDom.removeEventListener('mouseover', this.monitorOver);
             this.monitorOver = null;
             this.echartsDom.removeEventListener('mouseout', this.monitorOut);
             this.monitorOut = null;
         }
 ​
         /* 设置轮询开始位置 */
         setPlayIndex(index) {
             if (!this.echartsTarget) {
                 return;
             }
             this.echartsTarget.dispatchAction({
                 type: 'downplay',
                 seriesIndex: 0,
                 dataIndex: this.targetIndex,
             });
 ​
             this.targetIndex = index;
         }
 ​
         /* 更新数据 */
         updateData(chartOption, dataLength) {
             this.chartOption = chartOption;
             this.dataLength = dataLength;
             this.play();
         }
 ​
         /* 销毁,释放资源 */
         destroy() {
             if (!this.echartsTarget) {
                 return;
             }
             this.timer && clearInterval(this.timer);
             this.echartsDom = null;
             this.echartsTarget = null;
             this.chartOption = null;
             this.timer = null;
             this.step = null;
             this.targetIndex = null;
             //监听事件
             this.monitorOver && (this.monitorOver = null);
             this.monitorOut && (this.monitorOut = null);
         }
     }
 ​
     return ecahrtsTooltipPaly;
 });

类的使用

 this palyEchars = new ecahrtsTooltipPaly(echartsDom, echartsTarget, chartOption [,timer | ,dataLength | ,step | ,targetIndex ] )

注:中括号表示该参数可不传

入参说明

参数说明是否为必传项
echartsDomechars的div节点
echartsTarget使用ecahrts.init()生成的echars对象
chartOptionecahrts的options对象
timer计时器对象,如果当前页面只有一个计时器对象,可不传,有多个依照情况判断用户自行判断
dataLength数据长度
stepecahrt轮播的速度
targetIndexecahrts开始轮播的位置,默认0

API

API说明是否默认开启
init()轮播初始化,默认new的时候自动加载,执行其他函数
openEchartsMonitor()开启ecahrts移入监听,目前只实现鼠标选中数据对象,则下次轮播位置从当前选择对象开始(可能会有问题)
colseEchartsMonitor()关闭ecahrts的移入监听
play()ecahrts开始轮询,默认在init()内执行
stop()ecahrts停止轮询
verifyDomMonitor()验证是否存在dom节点的监听事件
openDomMonitor()开启dom节点的监听,即鼠标移入dom停止轮询,移出开始轮询,默认在init()内执行
closeDomMonitor()移出dom节点的监听,鼠标移入dom,将不再存在任何作用
setPlayIndex(index)更新轮播起始位置下标
updateData(option, dataLength)更新数据,当ecahrts发送更新时调用该api即可,dataLength可传可不传
destroy()释放资源,慎重使用

其他

 /* 调用轮播以及数据更新 */
 if (this.ecahrtsPlay) {
     //更新数据 => updateData的第二个参数可传可不传
     this.ecahrtsPlay.updateData(echartsConf.options, echartsConf.data.length);
 } else {
     //开启轮播
     that.ecahrtsPlay = new ecahrtsTooltipPaly(
         document.getElementById('echartsShowBox1'),
         echartsConf.instantiation,
         echartsConf.options,
         that.timer,
         echartsConf.data.length
     );
 }

项目演示地址:code.juejin.cn/pen/7273382…