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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/515744.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

jdbc连SQL server,显示1433端口连接失败解决方法

Exception in thread "main" com.microsoft.sqlserver.jdbc.SQLServerException: 通过端口 1433 连接到主机 localhost 的 TCP/IP 连接失败。错误:“connect timed out。请验证连接属性。确保 SQL Server 的实例正在主机上运行&#xff0c;且在此端口接受 TCP/IP 连接…

移动WEB开发之rem适配布局

一、rem 基础 rem 单位 rem (root em)是一个相对单位&#xff0c;类似于em&#xff0c;em是父元素字体大小。不同的是rem的基准是相对于html元素的字体大小。比如&#xff0c;根元素&#xff08;html&#xff09;设置font-size12px; 非根元素设置width:2rem; 则换成px表示就是2…

页面自适应

后续整理下自适应的集中方法 地址

【数据库】MySQL InnoDB存储引擎详解 - 读书笔记

MySQL InnoDB存储引擎详解 - 读书笔记 InnoDB 存储引擎概述InnoDB 存储引擎的版本InnoDB 体系架构内存缓冲池LRU List、Free List 和 Flush List重做日志缓冲&#xff08;redo log buffer&#xff09;额外的内存池 存储结构表空间系统表空间独立表空间通用表空间undo表空间临时…

如何彻底删除node和npm

如何彻底删除node和npm 前言&#xff1a; 最近做个项目把本地的node更新了&#xff0c;之前是v10.14.2更新至v16.14.0 &#xff0c;想着把之前的项目起来下&#xff0c;执行npm install 结果启动不了&#xff0c;一直报npm版本不匹配需要更新本地库异常… 找了几天发现是npm 和…

基于JAVA的汽车售票网站论文

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对汽车售票信息管理混乱&#xff0c;出错率高&#xff0c;信息安全性差…

从零到百万富翁:ChatGPT + Pinterest

原文&#xff1a;Zero to Millionaire Online: ChatGPT Pinterest 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 在社交媒体上赚取百万美元 - 逐步指南&#xff0c;如何在线赚钱版权 献给&#xff1a; 我将这本书&#xff0c;“从零到百万富翁在线&#xff1a;Chat…

Netty经典32连问

文章目录 1、Netty是什么&#xff0c;它的主要特点是什么&#xff1f;2、Netty 应用场景了解么&#xff1f;3、Netty 核心组件有哪些&#xff1f;分别有什么作用&#xff1f;4、Netty的线程模型是怎样的&#xff1f;如何优化性能&#xff1f;5、EventloopGroup了解么?和 Event…

【QT入门】 无边框窗口设计之实现圆角窗口

往期回顾&#xff1a; 【QT入门】对无边框窗口自定义标题栏并实现拖动和拉伸效果-CSDN博客 【QT入门】 自定义标题栏界面qss美化按钮功能实现-CSDN博客 【QT入门】 无边框窗口设计之实现窗口阴影-CSDN博客 【QT入门】 无边框窗口设计之实现圆角窗口 我们实际用到的很多窗口&am…

装饰工程管理系统|基于Springboot的装饰工程管理系统设计与实现(源码+数据库+文档)

装饰工程管理系统-项目立项子系统目录 目录 基于Springboot的装饰工程管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员功能实现 &#xff08;2&#xff09;合同报价管理 &#xff08;3&#xff09;装饰材料总计划管理 &#xff08;4&#xff0…

基本线段树以及相关例题

1.线段树的概念 线段树是一种二叉树&#xff0c;也就是对于一个线段&#xff0c;我们会用一个二叉树来表示。 这个其实就是一个线段树&#xff0c;我们会将其每次从中间分开&#xff0c;其左孩子就是左边的集合的和&#xff0c;其右孩子就是右边集合的和&#xff1b; 我们可以…

前端返回 List<Map<String, Object>>中的vaue值里面包含一个Bigdecimal类型,序列化时小数点丢失,如何解决?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

Windows 11安装kb5035853补丁时,提示错误0x800f0922,并且弹出“某些操作未按计划进行,不必担心,正在撤消更改。请不要关机”

Windows 11安装kb5035853补丁时&#xff0c;提示错误0x800f0922&#xff0c;并且还在重启后弹出“某些操作未按计划进行&#xff0c;不必担心&#xff0c;正在撤消更改。请不要关机”&#xff0c;按微软官方的作法是&#xff1a;https://learn.microsoft.com/zh-cn/windows/rel…

基于SpringBoot和Vue的音乐在线交流网站的设计和实现【附源码】

1、系统演示视频&#xff08;演示视频&#xff09; 2、需要交流和学习请联系

【PLC一体机】GX Works2编程控制步进电机正反转

今天博主和大家分享一下在GX Works2 中对PLC一体机编程&#xff0c;实现步进电机自动正反转的程序。 程序如下&#xff1a; 该程序有几个重要的地方和大家分享一下&#xff1a; 1、程序以中间寄存器M4开头。 博主想通过PLC一体机上的触摸屏控制程序是否运行&#xff0c;因此…

多类别分类器(Machine Learning研习十八)

多类别分类器 二元分类器可以区分两个类别&#xff0c;而多类别分类器&#xff08;也称为多叉分类器&#xff09;可以区分两个以上的类别。 一些 Scikit-Learn 分类器&#xff08;如 LogisticRegression、RandomForestClassifier 和 GaussianNB&#xff09;能够原生处理多个类…

各类系统业务功能架构图整理

一、前言 很多软件系统一直经久不衰&#xff0c;主要这些系统都是一些生产工作经营不可或缺的系统。比如财务系统&#xff0c;商城系统&#xff0c;支付系统&#xff0c;供应链系统&#xff0c;人力资源管理系统&#xff0c;ERP系统等等。这些系统不管大公司还是小公司往往都需…

VSCode美化

今天有空收拾了一下VSCode&#xff0c;页面如下&#xff0c;个人觉得还是挺好看的~~ 1. 主题 Noctis 色彩较多&#xff0c;有种繁杂美。 我使用的是浅色主题的一款Noctis Hibernus 2. 字体 Maple Mono 官网&#xff1a;Maple-Font 我只安装了下图两个字体&#xff0c;使…

jvm总结学习

四种加载器 1.启动类加载器 2.拓展类加载器 3.应用程序加载器 4.自定义加载器 沙箱机制 就是为了保证安全&#xff0c;增加的一些权限。 native方法区&#xff08;静态变量&#xff0c;常量&#xff0c;类信息&#xff08;构造方法&#xff0c;接口定义&#xff09;&…

Python 代码混淆工具概述

在保护Python代码安全方面&#xff0c;有多种混淆工具可供选择&#xff0c;包括 Cython, Nuitka, Pyminifier 和 IPA guard。本文将介绍这些工具的特点和适用情况&#xff0c;以及在实际应用中的注意事项。 &#x1f4dd; 摘要 本文探讨了几种常见的 Python 代码混淆工具&am…