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

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

优化之前的漏斗图:
vue3使用echarts漏斗,根据数据计算比例大小_第1张图片

优化之后的漏斗图:
vue3使用echarts漏斗,根据数据计算比例大小_第2张图片

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} 
{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>

你可能感兴趣的:(echarts,前端,vue3)