vue3+eachrts饼图轮流切换显示高亮数据

在这里插入图片描述

<template>
    <div class="charts-box">
      <div class="charts-instance" ref="chartRef">
      </div>
      // 自定义legend 样式
      <div class="charts-note">
      <span v-for="(items, index) in data.dataList" class="charts-legend">
        <span class="legend" :style="{background:colorList[index]}"></span>
        <span>{{items.name}}</span>
        <span style="color: #999999;margin-left: 5px;">{{((items.value / props.total)*100).toFixed(2) }}%</span>
      </span>
    </div>
    </div>
  </template>
  <script setup>
  import {ref, onMounted, onUnmounted, reactive, watch} from 'vue'
  import * as echarts from 'echarts'
  import useEmitter from "@/hooks/useEmitter";
  import {findRightBottomPie, removeTrailingZeros} from "@/views/BangFuData/service"; // 接口

  const props = defineProps(['timeRange', 'dictItem', 'total'])
  const emitter = useEmitter()
  const chartRef = ref()

  const data = reactive({
    dataList: [
        {
            "name": "中央统战部",
            "value": "4742.93",
            "count": null,
            "type": null
        },
        {
            "name": "民盟",
            "value": "439.47",
            "count": null,
            "type": null
        },
        {
            "name": "致公党",
            "value": "377.23",
            "count": null,
            "type": null
        },
        {
            "name": "农工党",
            "value": "1181.58",
            "count": null,
            "type": null
        },
        {
            "name": "民建",
            "value": "365.38",
            "count": null,
            "type": null
        },
        {
            "name": "民进",
            "value": "200.72",
            "count": null,
            "type": null
        },
        {
            "name": "全国工商联",
            "value": "2112.68",
            "count": null,
            "type": null
        },
        {
            "name": "民革",
            "value": "102.70",
            "count": null,
            "type": null
        },
        {
            "name": "九三学社",
            "value": "439.30",
            "count": null,
            "type": null
        },
        {
            "name": "台盟",
            "value": "24.50",
            "count": null,
            "type": null
        }
    ],
  })
  const colorList =['#876FFE', '#F85A8E','#E74C3C','#FFC476','#F1C40F','#80C269','#13B5B1','#54DCFF','#1A92FF','#5085FF', '#F85A8E','#E74C3C','#FFC476','#F1C40F','#80C269','#13B5B1']

  const findData = (callback) => {
    let rightBottomPieRes = findRightBottomPie(props.timeRange === 'previous' ? 2 : 1)
    rightBottomPieRes.then(res => {
      // let arr = []
      // props.dictItem.find(qhItem => {
      //   let result = res.find(item => item.name.indexOf(qhItem.label) > -1)
      //   if (result) {
      //     arr.push({name: qhItem.label, value: result.value})
      //   } else {
      //     arr.push({name: qhItem.label, value: 0})
      //   }
      // })
      data.dataList = res
      callback()
    })
  }

  let myChart = null
  const option = ref(null)
  const buildOption = () => {
    let _option = {
      tooltip: {
        show: false,
        trigger: 'item',
      },
      legend: {
        show: false,
        itemWidth: 12,
        itemHeight: 12,
        itemGap: 20,
        icon: 'roundRect',
        bottom: '5%',
        left: '45px',
        right: '45px',
        formatter: (name) => {
          let total = 0;
          let tarValue = 0;
          for (let i = 0; i < data.dataList.length; i++) {
            total += parseFloat(data.dataList[i].value);
          }
          for (let index = 0; index < data.dataList.length; index++) {
            if (name.indexOf(data.dataList[index].name)> -1) {
              if(total && total !== 0){
                tarValue = ((data.dataList[index].value / total)*100).toFixed(2);
              }
            }
          }
          // if(tarValue === 0){
          //   return `{oneone|${name}}`;
          // }
          return `{oneone|${name}}   {threethree|${removeTrailingZeros(tarValue)}%}`;
        },
        textStyle: {
          rich: {
            threethree: {
              color: "#999",
            }
          }
        }
      },
      title: {
            text: '0',//主标题文本
            subtext:'资金(万元)',//副标题文本
            right:'center',
            top:'42%',
            textStyle:{
                fontSize: '1.2rem',
                color:'#454c5c',
                align:'center'
            },
            subtextStyle:{
                fontFamily : "微软雅黑",
                fontSize: '0.8rem',
                color:'#6c7a89',
            }
        },
      color: colorList,
      series: [
        {
          name: '',
          type: 'pie',
          radius: ['35%', '55%'],
          center: ['50%', '50%'],
          avoidLabelOverlap: false,
          itemStyle: {
            borderRadius: 0,
            borderColor: '#fff',
            borderWidth: 2
          },
          // label: {
          //     show: false,
          //     position: 'center'
          // },
          emphasis: {
            label: {
              show: true,
              fontSize: 20,
              fontWeight: 'bold'
            },
            scale: true,
            scaleSize: 20
          },
          // labelLine: {
          //     show: false
          // },
          label: {
            show: true,
            alignTo: 'edge',
            formatter: '{name|{b}} {time|{d}%} \n',
            minMargin: 5,
            edgeDistance: 10,
            lineHeight: 15,
            rich: {
              name: {
                fontSize: 14,
                color: '#000'
              },
              time: {
                fontSize: 14,
                color: '#999'
              }
            }
          },
          labelLine: {
            show: true,
            length: 30,
            length2: 0,
            maxSurfaceAngle: 80
          },
          labelLayout: function (params) {
            const isLeft = params.labelRect.x < myChart.getWidth() / 2;
            const points = params.labelLinePoints;
            // Update the end point.
            points[2][0] = isLeft  ? params.labelRect.x : params.labelRect.x + params.labelRect.width;
            return {
              labelLinePoints: points
            };
          },
          data: data.dataList
        }
      ]
    }
    _option.series[0].data = data.dataList;
    option.value = _option
  }
  const handleChartLoop = (option, myChart) => {
      if (!myChart) {
          return;
      }
      let currentIndex = -1; // 当前高亮图形在饼图数据中的下标
      let timeTicket = setInterval(selectPie, 2000); // 设置自动切换高亮图形的定时器

      // 取消所有高亮并高亮当前图形
      function highlightPie() {
          // 遍历饼图数据,取消所有图形的高亮效果
          for (let idx in option.series[0].data) {
              myChart.dispatchAction({
                  type: "downplay",
                  seriesIndex: 0,
                  dataIndex: idx,
              });
          }
          // 高亮当前图形
          myChart.dispatchAction({
              type: "highlight",
              seriesIndex: 0,
              dataIndex: currentIndex,
          });
          let data = option.series[0].data[currentIndex] && option.series[0].data[currentIndex].value ? option.series[0].data[currentIndex].value : 0
          myChart.setOption({
            title: {
              text: removeTrailingZeros(parseFloat(data).toFixed(2))
            },
            series: {
              label: {
                show: false,
                formatter: () => {
                  if ((option.series[0].data[currentIndex] && option.series[0].data[currentIndex].value === 0)
                    || !props.total || props.total == 0) {
                    return `{name|${option.series[0].data[currentIndex].name}} {time|0%} \n`
                  }
                  let val = removeTrailingZeros(((option.series[0].data[currentIndex].value/props.total)*100).toFixed(2))
                  return `{name|${option.series[0].data[currentIndex].name}} {time|${val}%} \n`
                }
              }
            }
          })
      }

      // 用户鼠标悬浮到某一图形时,停止自动切换并高亮鼠标悬浮的图形
      myChart.on("mouseover", (params) => {
          clearInterval(timeTicket);
          currentIndex = params.dataIndex;
          highlightPie();
      });

      // 用户鼠标移出时,重新开始自动切换
      myChart.on("mouseout", (params) => {
          if (timeTicket) {
              clearInterval(timeTicket);
          }
          timeTicket = setInterval(selectPie, 1000);
      });

      // 高亮效果切换到下一个图形
      function selectPie() {
          let dataLen = option.series[0].data.length;
          currentIndex = (currentIndex + 1) % dataLen;
          highlightPie();
      }
  }

  watch(() => props.timeRange, (nv, ov) => {
    findData(()=>buildOption())
  })
  watch(()=>option.value,(newOption,oldOption)=>{
    if(myChart == null) {
      myChart = echarts.init(chartRef.value);
    }
    option.value && myChart && myChart.setOption(newOption)
    if(oldOption==null){
      option.value && myChart && handleChartLoop(option.value,myChart);
    } else {
      //option.value && myChart && handleChartLoop(option.value,myChart);
    }
  })
  onMounted(()=>{
      myChart = echarts.init(chartRef.value);
      findData(()=>buildOption());
      emitter.on('echartsTimeRangeChange',()=>setTimeout(() => myChart && myChart.resize({width:chartRef.value.clientWidth,height:chartRef.value.clientHeight}), 50))
      emitter.on('echartsUpdate',()=>myChart && myChart.resize({width:chartRef.value.clientWidth,height:chartRef.value.clientHeight}))
  })
  onUnmounted(()=>{
    emitter.off('echartsTimeRangeChange')
    emitter.off('echartsUpdate')
    myChart.dispose()
  })
  </script>
  <style scoped>
  .charts-box{
    height: calc(100% - 48px);
  }

.charts-instance{
  height: 60%;
  width: 100%;
  overflow: hidden;
}
.charts-note{
  margin-left: 15%;
  height: 40%;
  overflow: hidden;
}
.charts-legend {
  display: inline-block;
  vertical-align: middle;
  margin-top: 15px;
  width: 50%;
  font-size: 12px;
}
.legend {
  display: inline-block;
  vertical-align: middle;
  margin-right:5px;
  width: 12px;
  height: 12px;
  border-radius: 2px;
}
  </style>

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用 Vue3 和 Echarts 实现饼图的示例代码: 1. 安装 Echarts:`npm install echarts` 2. 引入 Echarts: ```javascript import echarts from "echarts"; import "echarts/lib/chart/pie"; import "echarts/lib/component/title"; import "echarts/lib/component/tooltip"; import "echarts/lib/component/legend"; ``` 3. 在 Vue3 组件中使用 Echarts: ```vue <template> <div ref="chart" style="height: 400px;"></div> </template> <script> import echarts from "echarts"; import "echarts/lib/chart/pie"; import "echarts/lib/component/title"; import "echarts/lib/component/tooltip"; import "echarts/lib/component/legend"; export default { mounted() { // 基于准备好的dom,初始化echarts实例 var myChart = echarts.init(this.$refs.chart); // 指定图表的配置项和数据 var option = { title: { text: "饼图示例", left: "center", }, tooltip: { trigger: "item", formatter: "{a} <br/>{b}: {c} ({d}%)", }, legend: { orient: "vertical", left: "left", data: ["直接访问", "邮件营销", "联盟广告", "视频广告", "搜索引擎"], }, series: [ { name: "访问来源", 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: "直接访问" }, { value: 310, name: "邮件营销" }, { value: 234, name: "联盟广告" }, { value: 135, name: "视频广告" }, { value: 1548, name: "搜索引擎" }, ], }, ], }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); }, }; </script> ``` 在上面的示例代码中,我们在 `mounted` 钩子函数中初始化了一个 Echarts 实例,并使用 `setOption` 方法将图表的配置项和数据传递给 Echarts 实例,从而显示饼图。 其中,`ref` 属性指定了图表所在的 DOM 元素,`title` 属性设置了图表标题,`legend` 属性设置了图例,`series` 属性设置了饼图数据和样式。 如果需要修改饼图的样式或数据,只需要更改 `option` 对象的属性即可。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值