Vue3 玫瑰图

效果图:

html 复制代码
<template>
  <div class="MultiPie">
    <div class="charts-box" ref="ChartsBox">
      <v-chart ref="vChartRef" :option="option"> </v-chart>

      <!-- 大圆圈 -->
      <div
        class="big-circle"
        :style="{
          width: option.bigCircleWidth,
          height: option.bigCircleWidth,
          top: option.bigCircleTop,
          left: option.bigCircleleft,
        }"
      ></div>

      <!-- 小圆圈 -->
      <div
        class="small-circle"
        :style="{
          width: option.smallCircleWidth,
          height: option.smallCircleWidth,
          top: option.smallCircleTop,
          left: option.smallCircleleft,
        }"
      ></div>
    </div>
  </div>
</template>
<script setup lang="ts">
import HcpPng from "/uicom-assets/images/common/hcp-bg.png";
import { ref, onMounted, reactive, getCurrentInstance } from "vue";
import VChart from "vue-echarts";
import { use } from "echarts/core";
import { CanvasRenderer } from "echarts/renderers";
import { PieChart } from "echarts/charts";
import {
  DatasetComponent,
  GridComponent,
  TooltipComponent,
  LegendComponent,
} from "echarts/components";
import { BarChart } from "echarts/charts";

const { proxy }: any = getCurrentInstance();

use([
  DatasetComponent,
  CanvasRenderer,
  BarChart,
  GridComponent,
  TooltipComponent,
  LegendComponent,
  PieChart,
]);

// 获取图表实例
const vChartRef = ref();
const ChartsBox = ref(null);

const chartData = ref([
  { value: 40, name: "最低生活保障" },
  { value: 33, name: "特困人员救助" },
  { value: 28, name: "流浪乞讨人员救助" },
  { value: 22, name: "受灾人员救助" },
  { value: 20, name: "临时救助" },
]);

const halfCircleItemArr = chartData.value.map((i) => {
  return {
    value: i.value,
    itemStyle: {
      color: "none",
      decal: {
        symbol: "none",
      },
    },
    label: {
      show: false,
    },
  };
});

const option = reactive({
  // 标签显示信息
  labelFormatInfo: "{b}\\n{c}万元",
  // 组件属性
  chartName: "玫瑰图",
  unit: "条",

  bigCircleTop: "75%",
  bigCircleleft: "50%",
  bigCircleWidth: "28px",

  smallCircleTop: "75%",
  smallCircleleft: "50%",
  smallCircleWidth: "16px",

  // 调整标签位置
  // XY
  lablePosition: [
    {
      x: 145,
      y: 230,
    },
    {
      x: 320,
      y: 130,
    },
    {
      x: 450,
      y: 150,
    },
    {
      x: 520,
      y: 200,
    },
    {
      x: 560,
      y: 280,
    },
    {
      x: 0,
      y: 0,
    },
    {
      x: 0,
      y: 0,
    },
    {
      x: 0,
      y: 0,
    },
    {
      x: 0,
      y: 0,
    },
    {
      x: 0,
      y: 0,
    },
    {
      x: 0,
      y: 0,
    },
    {
      x: 0,
      y: 0,
    },
    {
      x: 0,
      y: 0,
    },
  ],

  // 图表属性
  tooltip: {
    trigger: "item",
  },
  legend: {
    show: false,
  },

  color: [
    {
      type: "radial",
      x: 1,
      y: 0.75,
      r: 1,
      colorStops: [
        {
          offset: 0,
          color: "#0674F133", // 100% 处的颜色
        },
        {
          offset: 1,
          color: "#0674F1FF", // 0% 处的颜色
        },
      ],
      global: false, // 缺省为 false
    },
    {
      type: "radial",
      x: 1,
      y: 0.75,
      r: 1,
      colorStops: [
        {
          offset: 0,
          color: "#029CD433", // 100% 处的颜色
        },
        {
          offset: 1,
          color: "#029CD4FF", // 0% 处的颜色
        },
      ],
      global: false, // 缺省为 false
    },
    {
      type: "radial",
      x: 1,
      y: 0.75,
      r: 1,
      colorStops: [
        {
          offset: 0,
          color: "#2BA47133", // 0% 处的颜色
        },
        {
          offset: 1,
          color: "#2BA471FF", // 100% 处的颜色
        },
      ],
      global: false, // 缺省为 false
    },
    {
      type: "radial",
      x: 1,
      y: 0.75,
      r: 1,
      colorStops: [
        {
          offset: 0,
          color: "#F5BA1833", // 0% 处的颜色
        },
        {
          offset: 1,
          color: "#F5BA18FF", // 100% 处的颜色
        },
      ],
      global: false, // 缺省为 false
    },
    {
      type: "radial",
      x: 1,
      y: 0.75,
      r: 1,
      colorStops: [
        {
          offset: 0,
          color: "#E3731833", // 0% 处的颜色
        },
        {
          offset: 1,
          color: "#E37318FF", // 100% 处的颜色
        },
      ],
      global: false, // 缺省为 false
    },
  ],

  series: [
    {
      name: "玫瑰图",
      type: "pie",
      startAngle: 180,
      minAngle: 0,
      radius: [0, "80%"],
      center: ["50%", "75%"],
      roseType: "radius",
      itemStyle: {
        borderRadius: 0,
      },
      label: {
        show: false,
      },
      labelLine: {
        show: false,
      },
      emphasis: {
        label: {
          show: false,
        },
        labelLine: {
          show: false,
        },
      },
      data: <any>[],
    },
  ],
});

onMounted(() => {
  const numarr = chartData.value.map((i) => i.value);
  const maxValue = Math.max(...numarr);
  const radiusArr = numarr.map((i) => i / maxValue);
  const circleArrData = [...chartData.value, ...halfCircleItemArr];

  const circleArrSeries = circleArrData.map((item, i) => {
    return {
      name: option.chartName,
      type: "pie",
      minAngle: 25, // 最小角度
      startAngle: 180,
      radius: [
        radiusArr[i] ? (radiusArr[i] - 0.07) * 100 + "%" : "92%",
        radiusArr[i] ? (radiusArr[i] - 0.05) * 100 + "%" : "95%",
      ],
      center: ["50%", "75%"],
      itemStyle: {
        borderRadius: 0,
      },
      label: {
        show: true,
        width: 127,
        fontWeight: 700,
        overflow: "break",
        fontFamily: "AlibabaPuHuiTi_2_85_Bold",
        fontSize: 14,
        lineHeight: 18,
        color: "#FFFFFF",
        formatter: option.labelFormatInfo.replace(/\\n/g, "\n"),
      },

      labelLine: {
        show: false,
      },
      labelLayout: {
        align: "left",
        verticalAlign: "middle",
        x: option.lablePosition[i] ? option.lablePosition[i]["x"] : -10,
        y: option.lablePosition[i] ? option.lablePosition[i]["y"] : -15,
      },
      emphasis: {
        disabled: true,
        label: {
          show: true,
        },
      },
      data: circleArrData.map((e: any, j) => {
        let obj = {};
        if (j === i && j + 1 <= circleArrData.length / 2) {
          obj = {
            value: option.series[0].roseType === "radius" ? e.value : 30,
            name: e.name,
          };
        } else {
          obj = {
            value: option.series[0].roseType === "radius" ? e.value : 30,
            name: e.name,
            itemStyle: {
              color: "none",
              decal: {
                symbol: "none",
              },
            },
            label: {
              show: false,
            },
          };
        }
        return obj;
      }),
    };
  });

  circleArrSeries.map((i: any) => {
    option.series.push(i);
  });
  option.series[0].data = [...chartData.value, ...halfCircleItemArr];
});
</script>

<style lang="scss" scoped>
.MultiPie {
  background-color: #000;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: flex-end;
  .charts-box {
    width: 100%;
    height: 100%;
    position: relative;
    .big-circle {
      position: absolute;
      z-index: 99;
      width: 28px;
      height: 28px;
      background: #ffffff4d;
      border-radius: 50%;
      left: 50%;
      top: 75%;
      transform: translate(-50%, -50%);
    }
    .small-circle {
      position: absolute;
      z-index: 100;
      width: 16px;
      height: 16px;
      background: #ffffff;
      border-radius: 50%;
      left: 50%;
      top: 75%;
      transform: translate(-50%, -50%);
    }
  }
}
</style>
相关推荐
paopaokaka_luck1 天前
基于springboot+vue的益暖微光公益服务平台(DeepSeek公益助手、善款信息追溯、志愿服务积分闭环、ECharts运营分析、活动状态自动流转)
java·前端·javascript·spring boot·mysql·架构·echarts
汤米粥2 天前
2026年主流前端技术框架
vue·react·elementplus·tailwind css·angular‌·svelte‌·bootstrap‌
腾讯数据架构师2 天前
任务跑完怎么直接出图表?CubeStudio 任务可视化 ECharts 数据格式实操(CSV/JSON + metric.json,11 种图表一键渲染)
前端·json·echarts·数据可视化
codigger3 天前
Vue nextTick 到底在等什么?一篇讲透原理与那些年踩过的坑
程序员·vue·编程·异步更新·#人工智能
总要学点什么3 天前
第81篇:数据可视化-PM2.5分布——让圆点的胖瘦替每座城市报出浓度
前端·信息可视化·echarts·cesium·空间分析
咚咚咚小柒3 天前
【前端】LangChain.js学习
前端·javascript·人工智能·typescript·langchain·vue·ai编程
paopaokaka_luck3 天前
社区服务平台(加权协同过滤推荐、Jieba中文词频分析、WebSocket实时聊天、求助处理闭环、 活动积分闭环、ECharts多维分析)
java·前端·spring boot·mysql·echarts·mybatis
mmsx4 天前
Android 并发考古:newThread 与 RxJava 共存,以及 GlobalScope 的三宗罪
android·echarts·rxjava
DataGear4 天前
DataGear 6.1.1 发布,数据可视化分析平台
javascript·信息可视化·数据分析·echarts·数据可视化
paopaokaka_luck5 天前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法