vue项目中的echarts图表,实现自动轮播tooltip

鼠标不移入echarts图表的情况下,tootitip实现自动轮播
先看效果
鼠标不移入echarts图表的情况下,tootitip实现自动轮播
如图所示,可以实现tooltip从6月1日逐次跳到6月30日,来展示数据
之前引用别人的,封装的方法不够全面,主要出现两个问题。
问题1:点击tab按钮切换图表后,tooltip的会跳一次第一个图表的顺序,再跳一次当前这个图表的顺序(例如:物流明细的图表,tooltip展现到6月5日时,点击流向城市按钮后跳转到第二张图表,此时tooltip会先跳一下流向城市图表的第一个索引,再跳一次物流明细的6月6日对应的索引,再切换回物流明细,就会有三个索引来回跳…)初步研究,应该是方法里的seriesIndex在作祟,切换图表后就是插入一个索引。当然研究的不是很透彻,还需要echarts大神来解释,目前情况是对于菜鸟级别的功能能实现,没有明显bug就好了。
问题2:鼠标移入echarts图表再移出后,tooltip就不会自动轮播了。
前提自行参考echarts并了解关于tooltip的官方api里的方法。当然轮子自己不会造,还不会直接用嘛~
echarts官网对于tooltip方法详解

1、将自动轮播tooltip方法封装一下,放在src文件夹下新建的一个tooltip-auto-show-vue.js文件内
在这里插入图片描述

/**
 * echarts tooltip轮播
 * @param chart ECharts实例
 * @param chartOption echarts的配置信息
 * @param options object 选项
 * {
 *  interval    轮播时间间隔,单位毫秒,默认为2000
 *  loopSeries  boolean类型,默认为false。
 *              true表示循环所有series的tooltip,false则显示指定seriesIndex的tooltip
 *  seriesIndex 默认为0,指定某个系列(option中的series索引)循环显示tooltip,
 *              当loopSeries为true时,从seriesIndex系列开始执行。
 *  updateData  自定义更新数据的函数,默认为null;
 *              用于类似于分页的效果,比如总数据有20条,chart一次只显示5条,全部数据可以分4次显示。
 * }
 * @returns {{clearLoop: clearLoop}|undefined}
 */
 export function loopShowTooltip(chart, chartOption, options) {
    let defaultOptions = {
      interval: 2000,
      loopSeries: false,
      seriesIndex: 0,
      updateData: null,
    };
  
    if (!chart || !chartOption) {
      return;
    }
  
    let dataIndex = 0; // 数据索引,初始化为-1,是为了判断是否是第一次执行
    let seriesIndex = 0; // 系列索引
    let timeTicket = 0;
    let seriesLen = chartOption.series.length; // 系列个数
    let dataLen = 0; // 某个系列数据个数
    let chartType; // 系列类型
    let first = true;
    let lastShowSeriesIndex = 0;
    let lastShowDataIndex = 0;
  
    if (seriesLen === 0) {
      return;
    }
  
    // 待处理列表
    // 不循环series时seriesIndex指定显示tooltip的系列,不指定默认为0,指定多个则默认为第一个
    // 循环series时seriesIndex指定循环的series,不指定则从0开始循环所有series,指定单个则相当于不循环,指定多个
    // 要不要添加开始series索引和开始的data索引?
  
    if (options) {
      options.interval = options.interval || defaultOptions.interval;
      options.loopSeries = options.loopSeries || defaultOptions.loopSeries;
      options.seriesIndex = options.seriesIndex || defaultOptions.seriesIndex;
      options.updateData = options.updateData || defaultOptions.updateData;
    } else {
      options = defaultOptions;
    }
  
    // 如果设置的seriesIndex无效,则默认为0
    if (options.seriesIndex < 0 || options.seriesIndex >= seriesLen) {
      seriesIndex = 0;
    } else {
      seriesIndex = options.seriesIndex;
    }
  
    /**
     * 清除定时器
     */
    function clearLoop() {
      if (timeTicket) {
        clearInterval(timeTicket);
        timeTicket = 0;
      }
  
      chart.off('mousemove', stopAutoShow);
      zRender.off('mousemove', zRenderMouseMove);
      zRender.off('globalout', zRenderGlobalOut);
    }
  
    /**
     * 取消高亮
     */
    function cancelHighlight() {
      /**
       * 如果dataIndex为0表示上次系列完成显示,如果是循环系列,且系列索引为0则上次是seriesLen-1,否则为seriesIndex-1;
       * 如果不是循环系列,则就是当前系列;
       * 如果dataIndex>0则就是当前系列。
       */
      let tempSeriesIndex =
        dataIndex === 0
          ? options.loopSeries
            ? seriesIndex === 0
              ? seriesLen - 1
              : seriesIndex - 1
            : seriesIndex
          : seriesIndex;
      let tempType = chartOption.series[tempSeriesIndex].type;
  
      if (tempType === 'pie' || tempType === 'radar' || tempType === 'map') {
        chart.dispatchAction({
          type: 'downplay',
          seriesIndex: lastShowSeriesIndex,
          dataIndex: lastShowDataIndex,
        }); // wait 系列序号为0且循环系列,则要判断上次的系列类型是否是pie、radar
      }
    }
  
    /**
     * 自动轮播tooltip
     */
    function autoShowTip() {
      let invalidSeries = 0;
      let invalidData = 0;
      function showTip() {
        // chart不在页面中时,销毁定时器
        let dom = chart.getDom();
        if (document !== dom && !document.documentElement.contains(dom)) {
          clearLoop();
          return;
        }
  
        // 判断是否更新数据
        if (
          dataIndex === 0 &&
          !first &&
          typeof options.updateData === 'function'
        ) {
          options.updateData();
          chart.setOption(chartOption);
        }
  
        let series = chartOption.series;
        let currSeries = series[seriesIndex];
        if (
          !series ||
          series.length === 0 ||
          !currSeries ||
          !currSeries.type ||
          !currSeries.data ||
          !currSeries.data.length
        ) {
          return;
        }
  
        chartType = currSeries.type; // 系列类型
        dataLen = currSeries.data.length; // 某个系列的数据个数
  
        let tipParams = {
          seriesIndex: seriesIndex,
        };
        switch (chartType) {
          case 'pie':
            // 处理饼图中数据为0或系列名为空的不显示tooltip
            if (
              !currSeries.data[dataIndex].name ||
              currSeries.data[dataIndex].name === '空' ||
              !currSeries.data[dataIndex].value
            ) {
              invalidData += 1;
              dataIndex = (dataIndex + 1) % dataLen;
              if (options.loopSeries && dataIndex === 0) {
                // 数据索引归0表示当前系列数据已经循环完
                // 无效数据个数个总数据个数相等,则该系列无效
                if (invalidData === dataLen) {
                  invalidSeries += 1;
                }
  
                // 新系列,重置无效数据个数
                invalidData = 0;
  
                // 系列循环递增1
                seriesIndex = (seriesIndex + 1) % seriesLen;
                // 系列数循环至起始值时重置无效系列数
                if (seriesIndex === options.seriesIndex) {
                  if (seriesLen !== invalidSeries) {
                    // 下一次系列轮回,重置无效系列数
                    invalidSeries = 0;
                    showTip();
                  } else {
                    // 下一次系列轮回,重置无效系列数
                    invalidSeries = 0;
                    clearLoop();
                  }
                } else {
                  showTip();
                }
              } else if (!options.loopSeries && dataIndex === 0) {
                if (dataLen !== invalidData) {
                  invalidData = 0;
                  showTip();
                } else {
                  invalidData = 0;
                  clearLoop();
                }
              } else {
                showTip();
              }
  
              return;
            }
          // eslint-disable-next-line no-fallthrough
          case 'map':
          case 'chord':
            tipParams.name = currSeries.data[dataIndex].name;
            break;
          case 'radar': // 雷达图
            tipParams.seriesIndex = seriesIndex;
            // tipParams.dataIndex = dataIndex;
            break;
          case 'lines': // 线图地图上的lines忽略
            dataIndex = 0;
            seriesIndex = (seriesIndex + 1) % seriesLen;
            invalidSeries++; // 记录无效系列数,如果无效系列数和系列总数相等则取消循环显示
            if (seriesLen !== invalidSeries) {
              showTip();
            } else {
              clearLoop();
            }
            return;
          default:
            tipParams.dataIndex = dataIndex;
            break;
        }
  
        if (chartType === 'pie' || chartType === 'radar' || chartType === 'map') {
          if (!first) {
            cancelHighlight();
          }
  
          // 高亮当前图形
          chart.dispatchAction({
            type: 'highlight',
            seriesIndex: seriesIndex,
            dataIndex: dataIndex,
          });
        }
  
        // 显示 tooltip
        tipParams.type = 'showTip';
        chart.dispatchAction(tipParams);
  
        lastShowSeriesIndex = seriesIndex;
        lastShowDataIndex = dataIndex;
  
        dataIndex = (dataIndex + 1) % dataLen;
        if (options.loopSeries && dataIndex === 0) {
          // 数据索引归0表示当前系列数据已经循环完
          invalidData = 0;
          seriesIndex = (seriesIndex + 1) % seriesLen;
          if (seriesIndex === options.seriesIndex) {
            invalidSeries = 0;
          }
        }
  
        first = false;
      }
  
      showTip();
      timeTicket = setInterval(showTip, options.interval);
    }
  
    // 关闭轮播
    function stopAutoShow() {
      if (timeTicket) {
        clearInterval(timeTicket);
        timeTicket = 0;
  
        if (chartType === 'pie' || chartType === 'radar' || chartType === 'map') {
          cancelHighlight();
        }
      }
    }
  
    let zRender = chart.getZr();
  
    function zRenderMouseMove(param) {
      if (param.event) {
        // 阻止canvas上的鼠标移动事件冒泡
        // param.event.cancelBubble = true;
      }  
      stopAutoShow();
    }
  
    // 离开echarts图时恢复自动轮播
    function zRenderGlobalOut() {
      // console.log("移出了")
      // console.log(timeTicket)
      if (!timeTicket) {
        autoShowTip();
      }
    }
  
    // 鼠标在echarts图上时停止轮播
    chart.on('mousemove', stopAutoShow);
    zRender.on('mousemove', zRenderMouseMove);
    zRender.on('globalout', zRenderGlobalOut);
  
    autoShowTip();
  
    return {
      clearLoop: clearLoop
    };
  }

2、在需要使用该方法的文件里引入

import { loopShowTooltip } from "../../../tooltip-auto-show-vue.js";
export default {
  data() {
    return {
      tootipTimer:""
    };
  },
}

3、在chart方法中,引用刚才封装的js方法

 	  myChart.setOption(option);
      this.tootipTimer && this.tootipTimer.clearLoop(); // this.tootipTimer 在data里定义
      this.tootipTimer = 0;
      // 调用轮播的方法
      this.tootipTimer = loopShowTooltip(myChart, option, {
        interval: 2000, // 轮播间隔时间
        loopSeries: true, // 是否开启轮播循环
        // loopSeries: boolean类型,默认为false。true表示循环所有series的tooltip;false则显示指定seriesIndex的tooltip。
        // seriesIndex: 默认为0,指定某个系列(option中的series索引)循环显示tooltip,当loopSeries为true时,从seriesIndex系列开始执行。
      });

注:针对刚才的问题2,我的解决方法是在main.js全局引用echarts,在基于准备好的dom,初始化echarts实例时采用this.$echarts.init()并非echart.init().

let myChart = this.$echarts.init(document.getElementById(id));

当然,这是机缘巧合发现这样可以行得通,不知道其他因素影响会不会再次出现这个bug…

  • 6
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值