Taro Echarts封装内外环形饼图

环形图是一种特殊的饼图,它由一个内圆和一个外圆组成,中间的部分是空的,形成一个环形。这种图表非常适合用来展示占比关系,同时保持视觉上的吸引力

封装组件

tsx 复制代码
import { StandardProps, View } from "@tarojs/components";
import { useMemoizedFn } from "ahooks";
import { useEffect, useState } from "react";
import { EchartsRef } from "src/components/ec-canvas/typings";
//@ts-ignore ts-nocheck
import * as echarts from "src/components/ec-canvas/echarts";

interface Props extends StandardProps {
  data: any[],
  total?: number,
}
const CircularPieChart: React.FC<Props> = ({ data, total }) => {

  const [chartRef, setChartRef] = useState<EchartsRef>();

  const onInit = useMemoizedFn((canvas, width, height, dpr) => {
    const chart = echarts.init(canvas, null, {
      width: width,
      height: height,
      devicePixelRatio: dpr, // 像素
    });
    canvas.setChart(chart);
    setChartRef(chart);
    return chart;
  });

  const setOption = useMemoizedFn(() => {
    const option = {
      // backgroundColor: '#1d2239',
      // tooltip: {
      //   trigger: 'item',
      //   formatter: "{a} <br/>{b}: {c} ({d}%)"
      // },
      title: {
        text: '总好友数',
        subtext: total,
        x: 'center',
        y: 'center',
        textStyle: {
          fontWeight: 'normal',
          fontSize: 16
        }
      },
      color: data.map((item) => item.color),
      legend: { //图例组件,颜色和名字
        left: '0',
        top: '50',
        orient: 'vertical',
        itemGap: 12, //图例每项之间的间隔
        itemWidth: 10,
        itemHeight: 10,
        icon: 'rect',
        textStyle: {
          color: [],
          fontStyle: 'normal',
          fontFamily: '微软雅黑',
          fontSize: 12,
        }
      },
      series: [{
        name: '违规次数',
        type: 'pie',
        select: false,
        hoverAnimation: false,
        // selectedMode: 'single',
        silent: true,
        clockwise: false,
        minAngle: 25, //最小的扇区角度(0 ~ 360)
        center: ['50%', '50%'], //饼图的中心(圆心)坐标
        radius: [54, 96], //饼图的半径
        avoidLabelOverlap: true, //是否启用防止标签重叠F
        legendHoverLink: false,
        // itemStyle: { //图形样式
        //   normal: {
        //     borderColor: '#1e2239',
        //     borderWidth: 1.5,
        //   },
        // },
        label: { //标签的位置
          normal: {
            show: true,
            position: 'inside', //标签的位置
            formatter: "{d}%",
            textStyle: {
              color: '#fff',
              fontSize: 12,
            }
          },
          emphasis: {
            show: true,
            disable: false,  //是否关闭扇区高亮效果
            scale: false,    //扇区是否缩放
            textStyle: {
              fontWeight: 'bold'
            }
          }
        },
        data: data
      },
      {
        name: '',
        type: 'pie',
        clockwise: false,
        // selectedMode: 'single',
        hoverAnimation: false,
        silent: true,
        legendHoverLink: false,
        minAngle: 25, //最小的扇区角度(0 ~ 360)
        center: ['50%', '50%'], //饼图的中心(圆心)坐标
        radius: [54, 96], //饼图的半径
        itemStyle: { //图形样式
          normal: {
            borderColor: '#fff',
            borderWidth: 1.5,
          }
        },
        select: false,
        label: { //标签的位置
          normal: {
            position: 'outer', //标签的位置
            formatter: '{a|{b}}\n{hr|}\n{per|{c}}',
            rich: {
              a: {
                color: '#999999',
                fontSize: 11,
                lineHeight: 20,
                align: 'center'
              },
              hr: {
                width: '100%',
                height: 0,
                alien: 'center'
              },
              per: {
                color: '#000000',
                align: 'center',
                fontSize: 15,
              }
            },
            // formatter: function (params) {
            //   console.log('ss', params)
            //   return `${params.value}\n${params.name}`
            // },
            textStyle: {
              color: '#000',
              fontSize: 12,
              textAlign: 'center',
            },
          }
        },
        labelLine: { length: 4 },
        data: data
      }

      ]
    }
    chartRef?.setOption?.(option);
  });

  useEffect(() => {
    if (!chartRef || !data.length) return;
    if (chartRef) {
      setOption();
    }
    return () => {
      chartRef?.destroy?.();
    };
  }, [chartRef, data]);
  return (
    <>
      <View className="w-750 h-700 absolute -left-10">
        {/* @ts-ignore */}
        <ec-canvas
          class="circular-pie-chart"
          id={`circular-pie-chart${Math.random() * 10000}`}
          canvas-id={`circular-pie-chart${Math.random() * 10000}`}
          ec={{ onInit }}
        />
      </View>
    </>
  )
}

export default CircularPieChart;

使用

tsx 复制代码
import { View } from "@tarojs/components";
import Taro from "@tarojs/taro";
import CircularPieChart from "src/components/CircularPieChart";

const app: App.GlobalData = Taro.getApp();
const Demo = () => {

  let data = [
    { value: 0, name: 'AL注册客人', color: '#7C74BC' },
    { value: 76, name: 'AU注册会员', color: '#554C99' },
    { value: 13, name: '非会员客人', color: '#554C99' },
    { value: 46, name: '注册会员客人', color: '#E6E4F7' },
  ];

  return (
    <>
      <View className="page mt-300">
        <CircularPieChart data={data} ></CircularPieChart>

      </View>
    </>
  );
};

export default Demo;
相关推荐
逝水无殇13 小时前
HTML 文本格式化详解:掌握 <strong>、<em>、<mark>、<del> 等常用标签
前端·javascript·html
特立独行的猫a14 小时前
DeepSeek Harness插件和工具的区别介绍及开发入门指南
前端·ai·agent·插件·deepseek·harness
小新讲网安14 小时前
HTTP请求走私攻击实战:CL.TE与TE.CL绕过前端服务器全解析
服务器·前端·网络·web安全·http·架构·漏洞
风骏时光牛马14 小时前
AI办公系统异常事件复盘分析
前端
console.log('npc')14 小时前
React 19 + Vite 企业级前端项目:从零搭建到规范交付
前端·react.js·前端框架
程序员黑豆14 小时前
Java字符串常量池完全指南:原理、intern()方法与性能优化最佳实践
java·前端·ai编程
光影少年14 小时前
react离线缓存、图片缓存方案
开发语言·前端·javascript·react native·react.js·缓存·前端框架
Canace14 小时前
笔记本都合上了,Claude 为什么还能在手机上执行电脑上装的技能?
前端·人工智能·ai编程
cyadyx15 小时前
Vite 比 Webpack 构建效率更高
前端·webpack·node.js·vite
mCell17 小时前
AI 时代 SVG 画图的潜力
前端·agent·svg