Echarts大屏半饼图(自动轮播高亮、resize)

8 篇文章 0 订阅
7 篇文章 0 订阅

技术栈:Vue + ECharts.js

简介

某些情况,大屏页面需要实现一些比较美观的图表,常用的图表插件有echarts,此篇的实现效果为饼图半环形图南丁格尔玫瑰图的结合体。
这两种图具体实例可查看echarts官网
目标图:
目标图
echarts示例:
echarts 饼图
同时实现轮播高亮,采用定时循环操作,先调用echartsdownplay取消所有的高亮,再调用highlight高亮指定数据。
每次窗口大小改变时,进行监听,chart更新,调用resize方法,避免出现错乱效果。

实现

安装echarts插件

npm install echarts --save

页面布局

<template>
  <div>
    <div id="pieChart"></div>
  </div>
</template>
<style>
#pieChart {
  width: 500px;
  height: 250px;
  margin: 0 auto;
}
</style>

逻辑实现

resize

监听窗口resize事件,及时重绘图表。
其中,需要注意到keep-alive 缓存特殊的两个阶段,activated(组件激活时) 和deactivated(组件停用时) 。

  • activated(组件激活时) keep-alive 缓存的组件激活时调用。
  • deactivated(组件停用时) keep-alive 缓存的组件停用时调用。

添加keep-alive标签后会增加activated和deactivated这两个生命周期函数。

import { debounce } from '@/utils'

export default {
  data() {
    return {
      $_resizeHandler: null
    }
  },
  mounted() {
    this.initListener()
  },
  // 组件激活时
  activated() {
    if (!this.$_resizeHandler) {
      // avoid duplication init
      this.initListener()
    }

    // when keep-alive chart activated, auto resize
    this.resize()
  },

  beforeDestroy() {
    this.destroyListener()
  },

  // 组件停用时
  deactivated() {
    this.destroyListener()
  },
  methods: {
    
    // 初始化监听
    initListener() {
      this.$_resizeHandler = debounce(() => {
        this.resize()
      }, 100)
      window.addEventListener('resize', this.$_resizeHandler)
    },

    // 销毁监听
    destroyListener() {
      window.removeEventListener('resize', this.$_resizeHandler)
      this.$_resizeHandler = null
    },

    // 图表resize
    resize() {
      const { chart } = this
      chart && chart.resize()
    }
  }
}

常规debounce方法:

/**
 * @param {Function} func
 * @param {number} wait
 * @param {boolean} immediate
 * @return {*}
 */
export function debounce(func, wait, immediate) {
  let timeout, args, context, timestamp, result

  const later = function() {
    // 据上一次触发时间间隔
    const last = +new Date() - timestamp

    // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
    if (last < wait && last > 0) {
      timeout = setTimeout(later, wait - last)
    } else {
      timeout = null
      // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
      if (!immediate) {
        result = func.apply(context, args)
        if (!timeout) context = args = null
      }
    }
  }

  return function(...args) {
    context = this
    timestamp = +new Date()
    const callNow = immediate && !timeout
    // 如果延时不存在,重新设定延时
    if (!timeout) timeout = setTimeout(later, wait)
    if (callNow) {
      result = func.apply(context, args)
      context = args = null
    }

    return result
  }
}

图表效果绘制

import * as echarts from "echarts";
export default {
  name: "PieChart",
  data() {
    return {
      theChart: null,
    };
  },
  mounted() {
    this.renderChart();
  },
  methods: {
    // 渲染图表
    renderChart() {
      if (this.theChart) return;
      this.theChart = echarts.init(document.getElementById("pieChart"));
      const options = {
        series: [
          {
            type: "pie",
            radius: ["5%", "100%"],
            startAngle: 180,
            endAngle: 360,
            center: ["50%", "60%"],
            roseType: "radius",
            itemStyle: {
              borderRadius: 5,
              color: {
                type: "linear",
                x: 0,
                y: 0,
                x2: 0,
                y2: 1,
                colorStops: [
                  {
                    offset: 0,
                    color: "#005DEF", // 0% 处的颜色
                  },
                  {
                    offset: 0.6,
                    color: "#03255c", // 60% 处的颜色
                  },
                  {
                    offset: 1,
                    color: "#021739", // 100% 处的颜色
                  },
                ],
                global: false, // 缺省为 false
              },
            },
            // 正常不显示label
            label: {
              show: false,
            },
            // 高亮时效果
            emphasis: {
              label: {
                show: true,
              },
              itemStyle: {
                color: {
                  type: "linear",
                  x: 0,
                  y: 0,
                  x2: 0,
                  y2: 1,
                  colorStops: [
                    {
                      offset: 0,
                      color: "#910302", // 0% 处的颜色
                    },
                    {
                      offset: 1,
                      color: "#290208", // 100% 处的颜色
                    },
                  ],
                  global: false, // 缺省为 false
                },
              },
            },
            data: [
              { value: 10, name: "rose 1" },
              { value: 11, name: "rose 2" },
              { value: 12, name: "rose 3" },
              { value: 13, name: "rose 4" },
              { value: 14, name: "rose 5" },
              { value: 15, name: "rose 6" },
              { value: 16, name: "rose 7" },
              { value: 17, name: "rose 8" },
              { value: 18, name: "rose 9" },
              { value: 20, name: "rose 10" },
              { value: 25, name: "rose 11" },
              { value: 30, name: "rose 12" },
              { value: 35, name: "rose 13" },
              { value: 40, name: "rose 14" },
              { value: 45, name: "rose 15" },
              { value: 50, name: "rose 16" },
            ],
          },
        ],
      };
      this.theChart.setOption(options);
      this.handleChartLoop(options, this.theChart);
    },

    // 循环高亮
    handleChartLoop(option, myChart) {
      if (!myChart) {
        return;
      }
      let currentIndex = -1; // 当前高亮图形在饼图数据中的下标
      if (this.changePieInterval) clearInterval(this.changePieInterval);
      this.changePieInterval = setInterval(selectPie, 1000); // 设置自动切换高亮图形的定时器

      // 取消所有高亮并高亮当前图形
      function highlightPie() {
        // 遍历饼图数据,取消所有图形的高亮效果
        for (var idx in option.series[0].data) {
          myChart.dispatchAction({
            type: "downplay",
            seriesIndex: 0,
            dataIndex: idx,
          });
        }
        // 高亮当前图形
        myChart.dispatchAction({
          type: "highlight",
          seriesIndex: 0,
          dataIndex: currentIndex,
        });
      }
      this.theChart.on("mouseover", (params) => {
        // 用户鼠标悬浮到某一图形时,停止自动切换并高亮鼠标悬浮的图形
        if (this.changePieInterval) clearInterval(this.changePieInterval);
        currentIndex = params.dataIndex;
        highlightPie();
      });

      this.theChart.on("mouseout", (params) => {
        // 用户鼠标移出时,重新开始自动切换
        if (this.changePieInterval) clearInterval(this.changePieInterval);
        this.changePieInterval = setInterval(selectPie, 2000);
      });
      // 高亮效果切换到下一个图形
      function selectPie() {
        var dataLen = option.series[0].data.length;
        currentIndex = (currentIndex + 1) % dataLen;
        highlightPie();
      }
    },
  },
};

效果

实现完成后的效果如图。
默认不显示数据的label,高亮时显示;鼠标悬停时,仅高亮当前数据;移开后,恢复自动轮播。
高亮效果

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值