vue3使用echarts漏斗,根据数据计算比例大小

2023-12-22 13:34:07

需求:我们在开发过程中会遇到漏斗图的使用,如果用echarts里面自带的算法绘制渲染漏斗图时候,如果后端给的数据相差不大很接近时候,漏斗图渲染的结果不明显看不出来变化的。

优化之前的漏斗图:
在这里插入图片描述

优化之后的漏斗图:
在这里插入图片描述

1、实现逻辑思路如下然后

首先我们要获取后端给的数据里面数量值。计算出最大的值max。然后计算每个value数量在最大值里面所占的比重大小。这样我们计算出来的漏斗比例就很均匀的分配出来了。

2、具体实现步骤如下

注意点:为了让漏斗自适应根据不同分辨率适配,我们这里使用了window.addEventListener(‘resize’, resize)进行控制,并且防止用户多次恶意操作,加了防抖的限制debounce


<template>
  <div class="annualrecruit-box">
     <div class="search-box">
       <el-date-picker
         v-model="state.annualrecruitform.year"
         @change="getAnnualDoctorData"
         placeholder="请选择年份" 
         :disabled-date="disabledDate"
         type="year" 
         format="YYYY" 
         value-format="YYYY"
         :clearable="false"
         :editable="false"
       >
       </el-date-picker>
     </div>
     <div style="height:420px" ref="categoryChart"></div>
   </div>
</template>

<script setup lang="ts" name="AnnualRecruitmentPatient">
import { GetYearRecruitTesteeConvertSummary } from '/@/api/dashboard/index'
import { reactive, onMounted, onBeforeUnmount, nextTick, ref } from 'vue';
import * as echarts from 'echarts';
import { debounce } from 'lodash-es';
const state = reactive({
 annualrecruitform: {
   year: ''
 },
 dataName: [],
 dataList: [ ] as any
});
const categoryChart = ref()
var myChart = {} as any
const resize = debounce(() => myChart && myChart.resize(), 200)
onMounted (() => {
 getCurrentTime()
 window.addEventListener('resize', resize);
})

onBeforeUnmount(() => {
 window.removeEventListener('resize', resize);
})

//禁用当前日期之后的日期
function disabledDate(time) {
 return time.getTime() > Date.now() - 8.64e7;
}

//获取当前覆盖时间
function getCurrentTime() {
 let currentTime = new Date(), year = currentTime.getFullYear()
 state.annualrecruitform.year = year.toString()
 getAnnualDoctorData()
}

function getAnnualDoctorData () {
 GetYearRecruitTesteeConvertSummary({ year: Number(state.annualrecruitform.year)}).then((res:any) => {
   if (res.data) {
     let legendData = []
     const datavallist = res.data.map((item) => {
         return item.summaryVal
     });
     const max = Math.max(...datavallist)
     if (res.data && res.data.length > 0) {
       legendData = res.data.map((item) => {
         return { name: item.summaryItemName, value: item.summaryVal * 100 / max, _value: item.summaryVal  }
       });
       state.dataName = res.data.map((item) => {
         return item.summaryItemName
       });
     }
     state.dataList = legendData   
     nextTick(() => {
       initEchartFunnel();
     });
     
   }
 });
}

function initEchartFunnel () {
 if (myChart != null && myChart != "" && myChart != undefined) {
  echarts.dispose(categoryChart.value)
 }
 myChart = echarts.init(categoryChart.value);
 const option = {
     title: {
         text: '',
         subtext: ''
     },
     tooltip: {
         trigger: 'item',
         formatter(e){
           return `${e.name} : ${e.data._value}`//将他动态设置 name就是名字 values是我给他新添加的真实数据
         } 
         // formatter: "{a} <br/>{b} : {c}%"
     },
     toolbox: {
       show: 1, x: 'right', y: 'bottom',
         feature: {
             // dataView: {readOnly: false},
             // restore: {},
             // saveAsImage: {}
         }
     },
     legend: {
         bottom: 5,//控制图例出现的距离  默认左上角
         left: 'center',//控制图例的位置
         data: state.dataName
     },

     color: [ '#316BF4', '#0CBAD3', '#7F66EB', '#F3C949', '#FA984E', '#F57373' ],

     series: [
         {
             name:'漏斗图',
             type:'funnel',
             left: '5%',
             top: 60,
             bottom: 60,
             width: '90%',
             min: 0,
             max: 100,
             minSize: '0%',
             maxSize: '100%',
             gap: 2,
             label: {
                 show: true,
                 position: 'inside',
                 formatter(e){
                   return `${e.name}${e.data._value}`
                 }
             },
             labelLine: {
                 length: 10,
                 lineStyle: {
                     width: 1,
                     type: 'solid'
                 }
             },
             itemStyle: {
                 borderColoer: '#fff',
                 borderWidth: 1
             },
             emphasis: {
                 label: {
                     fontSize: 20
                 }
             },
             data: state.dataList
         }
     ]
 };

 myChart.setOption(option);
}
</script>

<style scoped lang="scss">
.annualrecruit-box {
 .search-box {
   text-align: right;
   margin-bottom: 20px;
 }
}
</style>

文章来源:https://blog.csdn.net/qq_44552416/article/details/135148954
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。