当前位置: 首页 > news >正文

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>
http://www.cnnetsun.cn/news/137154.html

相关文章:

  • 15、系统管理脚本实用指南
  • 怎么选一款适合大面积清洁的多功能全自动洗地机呢?
  • 使用matlab编写m脚本,编写无迹卡尔曼滤波算法(UKF)估计电池SOC,注释清晰
  • 教培行业新媒体运营困境凸显!这款软件或成转型制胜法宝?
  • Photoshop Neural Filters:把“引擎截图”秒变“电影级美宣”?AI 深度模糊与色彩迁移工作流
  • 基于matlab的多目标优化算法NSGA3,动态输出优化过程,得到最终的多目标优化结果。 数据...
  • 12.18
  • COCO 数据集
  • 国内好用的测试用例管理工具有哪些?
  • 24、COM+ 事务管理与补偿资源管理器详解
  • YOLO深度学习模型的训练参数配置与优化
  • 数字孪生可视化模板怎么用?5大行业Demo拆解,帮你快速复用提效
  • 必藏!程序员转型AI大模型:机遇、路径与成功率拆解
  • 《智构空间:AIOS 与全时域 3D 交互范式》第 0 篇:前言 —— 触摸语义的厚度
  • 如何将照片从 Android 传输到 Android
  • 前端Vue使用js-audio-plugin实现录音功能
  • 测试用例之翻页功能详解
  • 音乐平台歌曲盗版维权全攻略:权利卫士录屏取证+可信时间戳认证实操指南
  • 根据您提供的 package.json 片段,涉及的 @vue/cli-plugin-babel 和 @vue/cli-service 版本为 ~4.2.0。以下是针对该版本的详细解决方案,结合相关依
  • electron-egg打包win7
  • 8种网络故障分析及测试命令大全
  • 新人必看盘点知名CTF练习靶场,从零基础入门到精通,收藏这一篇就够了!
  • Pythonselenium自动化测试实战项目
  • 关于Comtos Linux (朱雀)主体源码的选择
  • 超级Mini小车功能说明
  • STC32G12单片机替换成STC32F12单片机,直接替换的结果
  • SIEMENS 6SL3210-1PE33-0CL0 变频器
  • 软件测试常用的7种方法,最后一个是升职加薪关键!(零基础小白转行IT互联网高效进阶)
  • 【RTOS】EasyLog的移植与使用
  • 在数据库里玩“平行宇宙”:MatrixOne Data Branch 让数据也拥有Git 的分支/合并/对比/回滚(含跨集群同步)