news 2026/5/1 5:04:06

Vue3 漏斗图

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue3 漏斗图

三种效果图:

图一:

<template> <v-chart ref="vChartRef" :option="option"></v-chart> </template> <script setup lang="ts"> import { ref, computed, PropType, nextTick } from "vue"; import VChart from "vue-echarts"; import { use } from "echarts/core"; import { CanvasRenderer } from "echarts/renderers"; import { FunnelChart } from "echarts/charts"; import cloneDeep from "lodash/cloneDeep"; import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent, } from "echarts/components"; use([ DatasetComponent, CanvasRenderer, FunnelChart, GridComponent, TooltipComponent, LegendComponent, ]); // 获取图表实例 const vChartRef = ref(); const chartData = ref<any>([ { name: "data1", value: 20, }, { name: "data2", value: 40, }, { name: "data3", value: 60, }, { name: "data4", value: 80, }, { name: "data5", value: 100, }, ]); const seriesItem = ref<any>({ type: "funnel", top: 70, left: "10%", width: "80%", min: 0, minSize: "0%", maxSize: "100%", sort: "descending", // descending | ascending gap: 5, label: { show: true, position: "inside", fontSize: 12, }, itemStyle: { borderColor: "#fff", borderWidth: 0, }, emphasis: { label: { fontSize: 20, }, }, data: <any>[], }); const getSeries = () => { let series: any = []; const values = chartData.value; //系列模板 let item = cloneDeep(seriesItem.value); item.data = values; series.push(item); return series; }; const option = ref<any>({ tooltip: {}, legend: {}, series: getSeries(), }); </script>

图二:

<template> <v-chart ref="vChartRef" :option="option"></v-chart> </template> <script setup lang="ts"> import { ref, computed, PropType, nextTick } from "vue"; import VChart from "vue-echarts"; import { use } from "echarts/core"; import { CanvasRenderer } from "echarts/renderers"; import { FunnelChart } from "echarts/charts"; import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent, } from "echarts/components"; use([ DatasetComponent, CanvasRenderer, FunnelChart, GridComponent, TooltipComponent, LegendComponent, ]); // 获取图表实例 const vChartRef = ref(); const chartData = ref<any>({ dimensions: ["categoryName", "categoryNum"], source: [ { categoryName: "施工管理", categoryNum: 20 }, { categoryName: "物管纠纷", categoryNum: 40 }, { categoryName: "房屋交易监管", categoryNum: 60 }, { categoryName: "街面秩序", categoryNum: 80 }, { categoryName: "拖欠克扣工资", categoryNum: 100 }, { categoryName: "产品质量问题", categoryNum: 88 }, { categoryName: "失业待遇", categoryNum: 64 }, ], }); // 排序函数 const sortBy = (property: string) => { return function (value1: any, value2: any) { let a = value1[property]; let b = value2[property]; if (a < b) { return 1; } if (a > b) { return -1; } return 0; }; }; // 数据处理 const source = [...chartData.value.source].sort(sortBy("categoryNum")); const total = source.reduce((prev: any, cur: any) => prev + cur.categoryNum, 0); const legendData = source.map((i: any) => { // 计算占比 const zb = (i.categoryNum / total) * 100; let percent = 0; if (zb - Math.floor(zb) > 0) { percent = Number(zb.toFixed(2)); } else { percent = zb; } // 文本换行 let text = i.categoryName; let length = text.length; let maxLineLength = 6; let lineCount = Math.ceil(length / maxLineLength); let lines = []; for (let j = 0; j < lineCount; j++) { let line = text.substr(j * maxLineLength, maxLineLength); lines.push(line); } const str = lines.join("\n"); return `${str}\n${i.categoryNum}次 | ${percent}%`; }); // 重新组装数据 const dataMap = { dimensions: chartData.value.dimensions, source: legendData.map((label: any, index: number) => ({ categoryName: label, categoryNum: source[index].categoryNum, title: source[index].categoryName, })), }; const option = ref<any>({ color: [ "#0674F1", "#029CD4", "#2BA471", "#F5BA18", "#E37318", "#D54941", "#E851B3", "#8E56DD", ], dataset: { ...dataMap }, legend: { type: "scroll", orient: "vertical", left: "65%", width: 90, height: "100%", itemGap: 8, data: legendData, }, series: [ { name: "Funnel", type: "funnel", top: "3%", left: "0%", width: "60%", height: "100%", min: 0, minSize: "0%", maxSize: "100%", sort: 'ascending', // descending | ascending gap: 2, colorBy: "data", label: { show: true, position: "inside", fontSize: 12, fontWeight: "bold", fontFamily: "Arial-BoldMT", color: "#fff", formatter: `{d}%`, }, itemStyle: { borderColor: "#fff", borderWidth: 0, shadowBlur: 0, }, emphasis: { label: { fontSize: 20, }, }, }, ], }); </script>

图三:

<template> <v-chart ref="vChartRef" :option="option"></v-chart> </template> <script setup lang="ts"> import { ref, computed, PropType, nextTick } from "vue"; import VChart from "vue-echarts"; import { use } from "echarts/core"; import { CanvasRenderer } from "echarts/renderers"; import { FunnelChart } from "echarts/charts"; import cloneDeep from 'lodash/cloneDeep' import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent, } from "echarts/components"; use([ DatasetComponent, CanvasRenderer, FunnelChart, GridComponent, TooltipComponent, LegendComponent, ]); // 获取图表实例 const vChartRef = ref(); const chartData = ref<any>({ dimensions: ["categoryName", "categoryNum"], source: [ { categoryNum: 10678, categoryName: "高中及以上学历", }, { categoryNum: 9678, categoryName: "专科及以上学历", }, { categoryNum: 6678, categoryName: "本科及以上学历", }, { categoryNum: 1678, categoryName: "硕士及以上学历", }, { categoryNum: 178, categoryName: "博士及以上学历", }, ], }); // 排序函数 const sortBy = (property: string) => { return function (value1: any, value2: any) { let a = value1[property]; let b = value2[property]; if (a < b) { return 1; } if (a > b) { return -1; } return 0; }; }; // 数据处理 const source = [...chartData.value.source].sort(sortBy("categoryNum")); const total = source.reduce((prev: any, cur: any) => prev + cur.categoryNum, 0); const legendData = cloneDeep(source).map(i => { // 计算占比 const zb = (i.categoryNum / total) * 100 let percent = 0 if(zb - Number(zb) > 0){ percent = Number(zb.toFixed(2)) }else{ percent = zb } // 文本换行 let text = i.categoryName; let length = text.length; let maxLineLength = 6; // 每行最多显示的字符数 let lineCount = Math.ceil(length / maxLineLength); // 计算需要几行 let lines = []; for (let i = 0; i < lineCount; i++) { let line = text.substr(i * maxLineLength, maxLineLength); lines.push(line); } const str = lines.join('\n'); return `${str}\n${i.categoryNum}次 | ${percent}%` }) // 重新组装数据 const dataMap = { dimensions: chartData.value.dimensions, source: legendData.map((label: any, index: number) => ({ categoryName: label, categoryNum: source[index].categoryNum, title: source[index].categoryName, })), }; const option = ref<any>({ color: [ "#0674F1", "#029CD4", "#2BA471", "#F5BA18", "#E37318", "#D54941", "#E851B3", "#8E56DD", ], dataset: { ...dataMap }, legend: { type: "scroll", orient: "vertical", left: "65%", width: 90, height: "100%", itemGap: 16, data: legendData, }, series: [ { name: "Funnel", type: "funnel", top: "3%", left: "0%", width: "60%", height: "100%", min: 0, minSize: "0%", maxSize: "100%", sort: "descending", // descending | ascending gap: 2, colorBy: "data", label: { show: true, position: "inside", fontSize: 12, fontWeight: "bold", fontFamily: "Arial-BoldMT", color: "#fff", // formatter: '{c}', formatter: (params: any) => { return params.value.categoryNum; }, }, itemStyle: { borderColor: "#fff", borderWidth: 0, shadowBlur: 0, }, emphasis: { label: { fontSize: 20, }, }, }, ], }); </script>
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 2:38:28

22、Web与互联网管理实用脚本介绍

Web与互联网管理实用脚本介绍 在Web与互联网管理领域,有许多实用的脚本可以帮助我们更高效地完成各种任务。下面将详细介绍几个实用脚本,包括外部链接检查、Apache密码管理以及文件同步。 1. 外部链接检查脚本(checkexternal) 在网站维护过程中,检查外部链接的有效性是…

作者头像 李华
网站建设 2026/4/30 22:07:39

31、日期与时间处理脚本及Windows 10安装Bash指南

日期与时间处理脚本及Windows 10安装Bash指南 一、GNU date的强大功能 GNU date是一个强大的工具,安装后,许多日期计算变得简单。例如判断某一年是否为闰年,只需使用以下代码: if [ $( date 12/31/$year +%j ) -eq 366 ]如果一年的最后一天是该年的第366天,那么这一年…

作者头像 李华
网站建设 2026/4/29 13:38:57

收藏备用!程序员入门大模型:从0到1的学习全攻略

打开招聘软件不难发现一个趋势&#xff1a;传统开发岗位竞争愈发激烈&#xff0c;但大模型相关岗位却一路“绿灯”——算法工程师、大模型应用开发、Prompt工程师等职位薪资水涨船高&#xff0c;甚至不少公司开出“零基础培训入职”的条件。对程序员来说&#xff0c;现在学大模…

作者头像 李华
网站建设 2026/4/18 8:32:37

被 C 盘折磨这么多年,这次是最轻松的一次

我的 C 盘爆红了。 断断续续用安全软件清理了几次&#xff0c; 可越到后面&#xff0c; 就只能清理出几 M 的空间。 如果放在两年前&#xff0c; 下面我大概率会&#xff1a; 网上找一个 C 盘清理软件 → 被安装了全家桶软件 → 电脑彻底卡死。 但这次&#xff0c;我的行为习惯…

作者头像 李华
网站建设 2026/4/19 3:30:22

python-uniapp微信小程序的疫苗接种综合服务预约系统的设计与实现_8nt0wdue

文章目录系统截图项目技术简介可行性分析主要运用技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;系统截图 python-uniapp_8nt0wdue 微信小程序的疫苗接种综合服务预约系统的设计与实现 项目技术简介 …

作者头像 李华
网站建设 2026/4/12 5:59:10

小程序python-uniapp蓉城旅游门票酒店预订系统app 可视化4_y65c9x2y

文章目录系统截图项目技术简介可行性分析主要运用技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;系统截图 小程序小程序python-uniappapp可视化4_y65c9x2y 蓉城旅游门票酒店预订系统python-uniapp_98…

作者头像 李华