echarts饼状图自定义lengend点击后对应的扇形区域高亮

echarts yekong

echarts大屏项目开发中,需要实现一个功能,饼状图点击扇形区域后对应的自定义lengend高亮,点击自定义lengend后,对应的扇形区域高亮。

echarts扇形图自定义lengend点击后对应的扇形区域高亮

动态效果

echarts相关代码

<template>
  <div class="echartsBody">
    <div class="echartsBody1" ref="echarts1"></div>
    <div class="echartsBody2" v-if="num">
      <div class="echartsTitle">
        <gsapNum :number="num"></gsapNum>
      </div>
    </div>
  </div>
</template>

<script>
import * as echarts from "echarts"
import gsapNum from "@/components/gsapNum/index.vue";

export default {
  name: 'echarts1',
  components: {gsapNum},
  data() {
    return {
      num: 0,
      name: ''
    }
  },
  props: {
    list: {
      type: Array,
      default() {
        return [];
      }
    },
    shadowColor: {
      type: String,
      default() {
        return 'rgba(254, 175, 87, 0.5)';
      }
    },
    title: {
      type: String,
      default() {
        return '总数';
      }
    },
    total: {
      type: String,
      default() {
        return 0;
      }
    },
  },
  mounted() {
    var that = this;
    const viewElem = document.body;
    // 监听窗口变化,重绘echarts
    const resizeObserver = new ResizeObserver(() => {
      setTimeout(() => {
        that.drawEcharts();
      }, 300)
    });
    resizeObserver.observe(viewElem);
  },
  computed: {
    colorList: function () {
      var that = this;
      var colorList = []
      that.list.forEach((type) => {
        var color = new echarts.graphic.LinearGradient(0, 0, 1, 1, [{
          offset: 0,
          color: type.color1
        }, {
          offset: 1,
          color: type.color2
        }])
        colorList.push(color)
      });
      return colorList
    }
  },
  watch: {
    list() {
      this.drawEcharts()
    },
    name(newName, oldName) {
      let index = this.list.findIndex(item => item.name === newName);
      if (index !== -1) {
        let myChart = echarts.init(this.$refs.echarts1);
        // 取消之前高亮的扇形区域
        myChart.dispatchAction({
          type: 'downplay',
          seriesIndex: 0
        });

        // 高亮当前点击的扇形区域
        myChart.dispatchAction({
          type: 'highlight',
          seriesIndex: 0,
          dataIndex: index
        });
      }
    },
  },
  methods: {
    getName(e) {
      this.name = e
      this.list.forEach((type, index) => {
        if (type.name == e) {
          this.num = type.value
        }
      })
    },
    drawEcharts() {
      var that = this
      let myChart = echarts.init(this.$refs.echarts1)
      window.addEventListener('resize', function () {
        that.drawEcharts()
      })
      var colors = this.colorList
      var data = []
      var maxIndex = 0
      var maxValue = 0
      that.list.forEach((type, index) => {
        if (type.checked) {
          var datas = {
            ...type,
            itemStyle: {
              normal: {
                borderColor: new echarts.graphic.LinearGradient(0, 0, 1, 1, [{
                  offset: 0,
                  color: type.color1
                }, {
                  offset: 1,
                  color: type.color2
                }]),
              }
            }
          }
          data.push(datas)
          if (type.value > maxValue) {
            maxValue = type.value
            maxIndex = index
            that.name = type.name
            that.num = type.value
            that.$emit('getName', that.name);
          }
        }
      });
      var option = {
        color: colors,
        tooltip: {
          trigger: 'item',
          backgroundColor: 'rgba(0, 0, 0, 0)', // 设置 tooltip 背景色为透明
          borderColor: 'rgba(0, 0, 0, 0)',
          opacity: 1,
          shadowColor: 'rgba(0, 0, 0, 0)', // 设置阴影颜色为透明
          shadowBlur: 0, // 设置阴影模糊度为0,即无阴影
          confine: true,
          // 使用自定义的 formatter 函数
          formatter: function (params) {
            // params 是一个包含了当前鼠标悬浮点的所有数据的对象
            return `
                <div class="tooltipWin">
                  <h4 class="tooltipTitle">${params.name}</h4>
                  <p>件数:  <span>${params.value}</span></p>
                  <p>百分比: <span>${params.percent}%</span></p>
                </div>
                `;

          }
        },
        series: [
          {
            name: '案件类别',
            type: 'pie',
            roundCap: true,
            radius: ['50%', '80%'],
            center: ['50%', '50%'],
            borderCap: 'round',
            label: {
              show: false,
              position: 'center',
              formatter: function (data) {
                return data.value;
              },
              textStyle: {
                fontSize: 36,
                fontFamily: 'D-DIN, D-DIN',
                fontWeight: 'bold',
                color: '#FDBA51'
              }
            },
            labelLine: {
              show: false,
              length: 1,
              length2: 10
            },
            data: data
          },
        ]
      }
      myChart.clear()
      myChart.resize()
      myChart.setOption(option)
      myChart.dispatchAction({
        type: 'highlight',
        seriesIndex: 0,
        dataIndex: maxIndex
      });
      myChart.on('click', function (param) {
        // 取消之前高亮的扇形区域
        myChart.dispatchAction({
          type: 'downplay',
          seriesIndex: 0
        });

        // 高亮当前点击的扇形区域
        myChart.dispatchAction({
          type: 'highlight',
          seriesIndex: 0,
          dataIndex: param.dataIndex
        });
        console.log(param)
        that.num = param.value
        that.name = param.name
        that.$emit('getName', param.name);
      });
    },
  }
}
</script>

<style lang="scss" scoped>
.echartsBody {
  position: relative;
  width: 50%;
  height: calc(100% - 0px);

  .echartsBody1 {
    position: relative;
    width: 100%;
    height: calc(100% - 0px);
  }

  .echartsBody2 {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: calc(100% - 0px);
    display: flex;
    justify-content: center;
    align-items: center;
    flex-wrap: nowrap;
    flex-direction: column;
    align-content: flex-start;
    pointer-events: none;

    .echartsTitle {
      font-size: 36px;
      font-family: DIN-Bold;
      font-weight: bold;
      font-style: normal;
      color: #FDBA51;
    }
  }
}

</style>
<style lang="scss">
.tooltipWin {
  background: rgba(0, 0, 0, 0.8);
  padding: 10px;

  .tooltipTitle {
    font-size: 16px;
    font-family: MicrosoftYaHeiSemibold;
    color: #FFFFFF;
    padding: 0;
    margin: 0;
  }

  p {
    font-size: 16px;
    font-family: MicrosoftYaHeiSemibold;
    color: #FFFFFF;
    padding: 0;
    margin: 0;

    span {
      font-size: 16px;
      font-family: MicrosoftYaHeiSemibold;
      color: #02E9F1;
    }
  }
}
</style>

自定义lengend相关代码

<template>
  <div class="echartsBodys">
    <echarts1 @getName="getName" title="总数" :total="total" :list="list" ref="echarts"></echarts1>
    <div class="list">
      <div class="listItem cur" @click="getChecked(item.name)" :class="{active:item.name==name}"
           v-for="(item,index) in list" :key="index">
        <div class="listIteml">
          <div class="dot"
               :style="'background: linear-gradient(80deg,'+item.color1+' 0%, '+item.color2+' 100%);'"></div>
          <span>{{ item.name }}</span>
        </div>
        <div class="listItemr">
          <em class="num">{{
              item.value
            }}</em>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import echarts1 from "./components/echarts.vue";

export default {
  name: "title",
  data() {
    return {
      name: '',
      list: [
        {
          name: '货币',
          value: 168,
          color1: 'rgba(0, 168, 255, 1)',
          color2: 'rgba(0, 168, 255, 1)',
          checked: true
        },
        {
          name: '调产',
          value: 589,
          color1: 'rgba(0, 238, 255, 1)',
          color2: 'rgba(0, 238, 255, 1)',
          checked: true
        },
        {
          name: '组合',
          value: 128,
          color1: 'rgba(255, 219, 113, 1)',
          color2: 'rgba(255, 219, 113, 1)',
          checked: true
        },
        {
          name: '迁建',
          value: 158,
          color1: 'rgba(255, 158, 116, 1)',
          color2: 'rgba(255, 158, 116, 1)',
          checked: true
        }]
    }
  },
  computed: {
    total: function () {
      var total = 0
      this.list.forEach((type) => {
        total += type.value
      });
      return total
    }
  },
  components: {echarts1},
  methods: {
    getChecked(name) {
      this.name = name
      this.$refs.echarts.getName(name)
    },
    getName(e) {
      this.name = e
      this.$emit('getName', e)
    }
  },
}
</script>

<style lang="scss" scoped>
.list {
  position: relative;
  width: calc(50% - 0px);
  margin-left: 0px;
  height: calc(100% - 0px);
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  flex-direction: column;
  align-content: flex-start;

  .listItem {
    font-size: 14px;
    display: flex;
    height: 30px;
    margin-left: 0px;
    width: calc(100% - 0px);
    justify-content: space-between;
    align-items: center;
    flex-wrap: nowrap;
    flex-direction: row;
    align-content: flex-start;
    cursor: pointer;

    .listIteml {
      display: flex;
      justify-content: flex-start;
      align-items: center;
      flex-wrap: nowrap;
      flex-direction: row;
      align-content: flex-start;
      font-size: 14px;
      font-family: MicrosoftYaHei;
      font-weight: 400;
      color: #FFFFFF;
      padding-left: 10px;
    }

    .listItemr {
      display: flex;
      justify-content: flex-end;
      align-items: center;
      flex-wrap: nowrap;
      flex-direction: row;
      align-content: flex-start;
      padding-right: 10px;

      span {
        font-size: 14px;
        font-family: PingFang SC-Regular, PingFang SC;
        font-weight: 400;
        color: rgba(255, 255, 255, 1);
      }

      p {
        font-size: 14px;
        font-family: MicrosoftYaHeiSemibold;
        color: #FFFFFF;
        margin-left: 4px;
      }
    }

    .dot {
      width: 8px;
      height: 8px;
      margin-right: 10px;
      flex-shrink: 0;
      border-radius: 50%;
    }

    .dot.disabled {
      background: rgba(#999, 0.8) !important;
    }

    span.disabled {
      color: rgba(#999, 0.8) !important;
    }

    .num {
      font-size: 20px;
      font-family: DIN-Bold;
      font-weight: bold;
      color: #00F1F7;
      font-style: normal;

    }
  }

  .listItem.active {
    background: url("./components/assets/bgAnimate.png") no-repeat;
    background-size: 100% 100%;
  }
}

.echartsBodys {
  width: 100%;
  position: relative;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: nowrap;
  flex-direction: row;
  align-content: flex-start;
}
</style>

喜欢