Echarts双层环图—实现鼠标移出数据项后保持聚焦

       最近突然遇到一个需求,Echarts的双层环图在鼠标移出数据项后,需要继续保持数据项聚焦。这里简单记录一下最后Vue的组件实现过程。

一、效果图

二、双层环图的实现 

        双层环图怎么实现就简单略过了。实际就是两个同颜色同数据项的环图在同一个圆心位置,叠在一起。

//这是实现双层环图的series,用的vue,因为需求问题,很多配置项都改成了变量,从父组件传入
series: [
          {
            name: this.chartName,
            type: 'pie',
            center: this.center,
            radius: this.outerRadius,
            avoidLabelOverlap: false,
            minAngle: 3,
            itemStyle: {
              borderColor: '#fff',
              borderWidth: 3
            },
            label: {
              show: false,
              position: 'center',
              formatter: "{b} \r\n {c}人"
            },
            emphasis: {
              label: {
                show: true,
                fontSize: 20,
                fontWeight: 'bold',
              }
            },
            labelLine: {
              show: false
            },
            data: this.chartData
          },
          // // 内圈
          {
            type: 'pie',
            center: this.center,
            radius: this.innerRadius,
            silent: true, //取消高亮
            minAngle: 3,
            label: {show: false, position: 'center'},
            itemStyle: {
              borderColor: '#fff',
              borderWidth: 3
            },
            data: this.chartData,
          }
        ]

三、鼠标悬停

       主要使用Echarts的API通过绑定mouseover以及mouseout事件,同时配合dispatchAction进行实现。附Echarts的文档简要说明。

API参数说明
echartsInstance.dispatchAction(payload: Object)

触发图表行为,例如图例开关legendToggleSelect, 数据区域缩放dataZoom,显示提示框showTip等等,更多见 action 和 events 的文档。

payload 参数可以通过batch属性同时触发多个行为。

注:在 ECharts 2.x 是通过 myChart.component.tooltip.showTip 这种形式调用相应的接口触发图表行为,入口很深,而且涉及到内部组件的组织。因此在 ECharts 3 里统一改为 dispatchAction 的形式。

echartsInstance.on

( eventName: string, handler: Function, context?: Object )

( eventName: string, query: string|Object, handler: Function, context?: Object )

绑定事件处理函数。

ECharts 中的事件有两种,一种是鼠标事件,在鼠标点击某个图形上会触发,还有一种是 调用 dispatchAction 后触发的事件。每个 action 都会有对应的事件,具体见 action 和 events 的文档。

如果事件是外部 dispatchAction 后触发,并且 action 中有 batch 属性触发批量的行为,则相应的响应事件参数里也会把属性都放在 batch 属性中。

//当检测到鼠标悬停事件,取消默认选中高亮
this.chart.on("mouseover", (e) => {
        if (e.seriesIndex === seriesIndex && e.dataIndex === dataIndex) {
          return;
        }
        this.chart.dispatchAction({
          type: "downplay",
          seriesIndex: seriesIndex,
          dataIndex: dataIndex,
        });
      });
//检测鼠标移出后显示之前默认高亮的那块
this.chart.on("mouseout", (e) => {
        dataIndex = e.dataIndex;
        seriesIndex = e.seriesIndex;
        this.chart.dispatchAction({
          type: "highlight",
          seriesIndex: e.seriesIndex,
          dataIndex: e.dataIndex,
        });
      });

四、完整组件代码

       最后是这个组件完整代码

<template>
  <div :class="className" :style="{height:height,width:width}"/>
</template>

<script>
import * as echarts from 'echarts';

import resize from '../mixins/resize'

export default {
  mixins: [resize],
  props: {
    className: {
      type: String,
      default: 'chart'
    },
    //容器宽度
    width: {
      type: String,
      default: '100%'
    },
    //容器高度
    height: {
      type: String,
      default: '100%'
    },
    //图表名称
    chartName: {
      type: String,
      required: true
    },
    //图表数据
    chartData: {
      type: Array,
      required: true
    },
    //圆心位置
    center: {
      type: Array,
      default: () => ['50%', '50%']
    },
    //内环半径
    innerRadius: {
      type: Array,
      default: () => ['50.5%', '55.5%']
    },
    //外环半径
    outerRadius: {
      type: Array,
      default: () => ['56%', '87%']
    },
    //颜色
    color: {
      type: Array,
      default: () => ['#5470c6', '#91cc75', '#fac858', '#ee6666', 
                      '#73c0de', '#3ba272', '#fc8452', '#9a60b4', 
                      '#ea7ccc']
    },
    forceIndex: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      chart: null,
      options: {
        tooltip: {
          trigger: 'item'
        },
        color: this.color,
        series: [
          {
            name: this.chartName,
            type: 'pie',
            center: this.center,
            radius: this.outerRadius,
            avoidLabelOverlap: false,
            minAngle: 3,
            itemStyle: {
              borderColor: '#fff',
              borderWidth: 3
            },
            label: {
              show: false,
              position: 'center',
              formatter: "{b} \r\n {c}人"
            },
            emphasis: {
              label: {
                show: true,
                fontSize: 20,
                fontWeight: 'bold',
              }
            },
            labelLine: {
              show: false
            },
            data: this.chartData
          },
          // // 内圈
          {
            type: 'pie',
            center: this.center,
            radius: this.innerRadius,
            silent: true, //取消高亮
            minAngle: 3,
            label: {show: false, position: 'center'},
            itemStyle: {
              borderColor: '#fff',
              borderWidth: 3
            },
            data: this.chartData,
          }
        ]
      }
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.initChart()
    })
  },
  beforeDestroy() {
    if (!this.chart) {
      return
    }
    this.chart.dispose()
    this.chart = null
  },
  watch: {
    chartData: function (newVal, oldVal) {
      this.chart.clear();
      this.options.series[0].data = this.chartData;
      this.options.series[1].data = this.chartData;
      this.chart.setOption(this.options, true);
      this.chart.dispatchAction({
        type: "highlight",
        seriesIndex: 0,
        dataIndex: 0
      })
    }
  },
  methods: {
    initChart() {
      this.chart = echarts.init(this.$el)
      this.chart.setOption(this.options)
      let dataIndex = 0;
      let seriesIndex = 0;
      //默认高亮数据项
      this.chart.dispatchAction({
        type: "highlight",
        seriesIndex: 0,
        dataIndex: this.forceIndex - 1 < 0 ? 0 : this.forceIndex - 1
      })
      //当检测到鼠标悬停事件,取消之前高亮
      this.chart.on("mouseover", (e) => {
        if (e.seriesIndex === seriesIndex && e.dataIndex === dataIndex) {
          return;
        }
        this.chart.dispatchAction({
          type: "downplay",
          seriesIndex: seriesIndex,
          dataIndex: dataIndex,
        });
      });
      //检测鼠标移出后显示之前默认高亮的那块
      this.chart.on("mouseout", (e) => {
        dataIndex = e.dataIndex;
        seriesIndex = e.seriesIndex;
        this.chart.dispatchAction({
          type: "highlight",
          seriesIndex: e.seriesIndex,
          dataIndex: e.dataIndex,
        });
      });
    }
  }
}
</script>

  • 20
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实现echarts双层例,你可以按照以下步骤进行操作: 1. 在HTML模板中添加一个盒子,用于放置表: ```html <div class="chartMachineStyle" ref="chartMachine"></div> ``` 2. 在CSS样式中设置盒子的尺寸: ```css .chartMachineStyle { height: 200px; width: 355px; } ``` 3. 在JavaScript中使用echarts库创建双层例的: ```javascript // 引入echarts库 import echarts from 'echarts'; // 获取盒子元素 const chartMachine = document.querySelector('.chartMachineStyle'); // 初始化表 const myChart = echarts.init(chartMachine); // 配置表选项 const option = { title: { text: '双层例', x: 'center' }, legend: { data: ['例1', '例2'], bottom: 10 }, series: [ { name: '例1', type: 'pie', radius: ['50%', '70%'], avoidLabelOverlap: false, label: { show: false, position: 'center' }, emphasis: { label: { show: true, fontSize: '30', fontWeight: 'bold' } }, labelLine: { show: false }, data: [ { value: 335, name: '数据1' }, { value: 310, name: '数据2' }, { value: 234, name: '数据3' }, { value: 135, name: '数据4' }, { value: 1548, name: '数据5' } ] }, { name: '例2', type: 'pie', radius: ['30%', '40%'], avoidLabelOverlap: false, label: { show: false, position: 'center' }, emphasis: { label: { show: true, fontSize: '30', fontWeight: 'bold' } }, labelLine: { show: false }, data: [ { value: 335, name: '数据1' }, { value: 310, name: '数据2' }, { value: 234, name: '数据3' }, { value: 135, name: '数据4' }, { value: 1548, name: '数据5' } ] } ] }; // 使用配置项显示表 myChart.setOption(option); ``` 这样就可以实现一个带有双层例的了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值