pip 与 requirements.txt
2025/12/18 22:17:40
三种效果图:
图一:
<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>