PieChart.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import React, { useMemo } from 'react';
  2. import { BaseChart, BaseChartProps } from './BaseChart';
  3. import type { TouchEvent, ChartsConfig, LegendConfig } from '../lib/charts/index';
  4. /**
  5. * 饼图类型
  6. */
  7. export type PieChartType = 'pie' | 'ring';
  8. /**
  9. * 饼图组件的 Props 接口
  10. */
  11. export interface PieChartProps extends Omit<BaseChartProps, 'type' | 'categories'> {
  12. /** 饼图类型 */
  13. pieType?: PieChartType;
  14. /** 是否显示图例 */
  15. legend?: boolean;
  16. /** 字体大小 */
  17. fontSize?: number;
  18. /** 背景颜色 */
  19. background?: string;
  20. /** 是否开启动画 */
  21. animation?: boolean;
  22. /** 是否显示数据标签 */
  23. dataLabel?: boolean;
  24. /** 环形图内径比例 (0-1) */
  25. ringWidth?: number;
  26. /** 额外饼图配置 */
  27. extra?: ChartsConfig['extra'];
  28. /** tooltip 格式化函数 */
  29. tooltipFormatter?: (item: any) => string;
  30. }
  31. /**
  32. * PieChart 饼图组件
  33. *
  34. * 用于显示占比数据的饼图,支持普通饼图和环形图
  35. */
  36. export const PieChart: React.FC<PieChartProps> = (props) => {
  37. const {
  38. pieType = 'pie',
  39. legend = true,
  40. fontSize = 11,
  41. background = '#FFFFFF',
  42. animation = true,
  43. dataLabel = true,
  44. ringWidth = 0.6,
  45. extra = {},
  46. tooltipFormatter,
  47. series = [],
  48. config = {},
  49. ...baseProps
  50. } = props;
  51. const chartRef = React.useRef<any>(null);
  52. /**
  53. * 默认配置
  54. */
  55. const defaultConfig = useMemo(() => {
  56. const legendConfig: LegendConfig = legend ? { show: true } : { show: false };
  57. return {
  58. legend: legendConfig,
  59. fontSize,
  60. background,
  61. animation,
  62. dataLabel,
  63. extra: {
  64. pie: {
  65. activeOpacity: 0.5,
  66. activeRadius: 10,
  67. offsetAngle: 0,
  68. ringWidth: pieType === 'ring' ? ringWidth : 0,
  69. labelWidth: 15,
  70. ringWidthRatio: pieType === 'ring' ? ringWidth : 0
  71. },
  72. ...extra
  73. }
  74. };
  75. }, [legend, fontSize, background, animation, dataLabel, pieType, ringWidth, extra]);
  76. /**
  77. * tooltip 事件处理
  78. */
  79. const handleTouchStart = (e: TouchEvent) => {
  80. if (chartRef.current) {
  81. if (tooltipFormatter) {
  82. chartRef.current.showToolTip(e, {
  83. formatter: tooltipFormatter
  84. });
  85. } else {
  86. chartRef.current.showToolTip(e, {
  87. formatter: (item: any) => {
  88. return item.name + ':' + item.data;
  89. }
  90. });
  91. }
  92. }
  93. baseProps.onTouchStart?.(e);
  94. };
  95. return (
  96. <BaseChart
  97. {...baseProps}
  98. series={series}
  99. type={pieType}
  100. config={{ ...defaultConfig, ...config }}
  101. onTouchStart={handleTouchStart}
  102. />
  103. );
  104. };
  105. export default PieChart;