From 5189fdb6211bef336f3eedd5cea5cff04254b7f9 Mon Sep 17 00:00:00 2001
From: mmc <1556375442@qq.com>
Date: Mon, 31 Aug 2026 11:27:25 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20=20=E6=8E=A7=E5=88=B6?=
=?UTF-8?q?=E5=8F=B0=E8=AD=A6=E5=91=8A=E4=BF=A1=E6=81=AF=20=E5=9B=BE?=
=?UTF-8?q?=E6=A0=87=E5=A4=A7=E5=B0=8F=E5=9C=A8=E5=88=9D=E5=A7=8B=E5=8C=96?=
=?UTF-8?q?=20=20=E4=BC=9A=E8=AD=A6=E5=91=8A=20=E9=95=BF=E5=AE=BD-1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/recharts.jsx | 295 +++++++++++++++++++++++++++++++-----
1 file changed, 258 insertions(+), 37 deletions(-)
diff --git a/src/components/recharts.jsx b/src/components/recharts.jsx
index e76d002..86e8136 100644
--- a/src/components/recharts.jsx
+++ b/src/components/recharts.jsx
@@ -1,6 +1,5 @@
-import React from 'react';
+import React, { useEffect, useRef, useState } from 'react';
import {
- ResponsiveContainer,
LineChart,
Line,
XAxis,
@@ -15,8 +14,10 @@ import {
Bar,
} from 'recharts';
-
+// =========================
// 默认颜色池
+// =========================
+
const DEFAULT_COLORS = [
'#1677ff',
'#52c41a',
@@ -29,11 +30,114 @@ const DEFAULT_COLORS = [
];
+// =========================
+// 通用自适应容器
+// =========================
+//
+// 不再使用 ResponsiveContainer。
+// 通过 ResizeObserver 获取真实尺寸,
+// 只有 width / height > 0 时才渲染 Recharts。
+// 这样可以彻底避免:
+//
+// width(-1) and height(-1)
+//
+// =========================
+
+const ChartResizeContainer = ({
+ children,
+ width = '100%',
+ height = 360,
+ className,
+ style,
+}) => {
+ const containerRef = useRef(null);
+
+ const [size, setSize] = useState({
+ width: 0,
+ height: 0,
+ });
+
+ useEffect(() => {
+ const element = containerRef.current;
+
+ if (!element) {
+ return;
+ }
+
+ const updateSize = () => {
+ const rect = element.getBoundingClientRect();
+
+ const nextWidth = Math.floor(rect.width);
+ const nextHeight = Math.floor(rect.height);
+
+ // 非法尺寸直接忽略
+ if (nextWidth <= 0 || nextHeight <= 0) {
+ return;
+ }
+
+ setSize((prev) => {
+ if (
+ prev.width === nextWidth &&
+ prev.height === nextHeight
+ ) {
+ return prev;
+ }
+
+ return {
+ width: nextWidth,
+ height: nextHeight,
+ };
+ });
+ };
+
+ // 首次主动测量
+ updateSize();
+
+ // 后续监听尺寸变化
+ const observer = new ResizeObserver(() => {
+ updateSize();
+ });
+
+ observer.observe(element);
+
+ return () => {
+ observer.disconnect();
+ };
+ }, []);
+
+ return (
+
+ {size.width > 0 && size.height > 0
+ ? React.cloneElement(children, {
+ width: size.width,
+ height: size.height,
+ })
+ : null}
+
+ );
+};
+
+
+// =========================
+// Universal Line Chart
+// =========================
export const UniversalLineChart = ({
- data,
+ data = [],
xKey,
- series,
+ series = [],
width = '100%',
height = 360,
showGrid = true,
@@ -43,6 +147,7 @@ export const UniversalLineChart = ({
smooth = true,
dot = false,
className,
+ style,
}) => {
return (
-
-
+
+
{showGrid && (
-
+
)}
+
{showTooltip && }
+
{showLegend && }
{series.map((item, index) => (
))}
-
+
);
};
+// =========================
+// Universal Bar Chart
+// =========================
export const UniversalBarChart = ({
- data,
+ data = [],
xKey,
- series,
+ series = [],
width = '100%',
height = 360,
showGrid = true,
@@ -102,6 +239,7 @@ export const UniversalBarChart = ({
radius = 6,
stack = false,
className,
+ style,
}) => {
return (
-
-
+
+
{showGrid && (
-
+
)}
+
{showTooltip && }
+
{showLegend && }
{series.map((item, index) => (
@@ -131,22 +282,35 @@ export const UniversalBarChart = ({
key={item.key}
dataKey={item.key}
name={item.name}
- fill={item.color || DEFAULT_COLORS[index % DEFAULT_COLORS.length]}
+ fill={
+ item.color ||
+ DEFAULT_COLORS[
+ index %
+ DEFAULT_COLORS.length
+ ]
+ }
barSize={barSize}
radius={radius}
- stackId={stack ? 'stack' : undefined}
+ stackId={
+ stack
+ ? 'stack'
+ : undefined
+ }
/>
))}
-
+
);
};
+// =========================
+// Universal Pie Chart
+// =========================
export const UniversalPieChart = ({
- data,
+ data = [],
width = '100%',
height = 360,
showLegend = true,
@@ -157,7 +321,7 @@ export const UniversalPieChart = ({
paddingAngle = 2,
showLabel = true,
className,
- style
+ style,
}) => {
return (
-
-
+
+
{showTooltip && }
+
{showLegend && }
(
|
))}
-
+
);
};
+
// =========================
// 使用示例
// =========================
export const DemoCharts = () => {
const lineData = [
- { month: '1月', uv: 400, pv: 240, amt: 240 },
- { month: '2月', uv: 300, pv: 456, amt: 300 },
- { month: '3月', uv: 500, pv: 139, amt: 200 },
- { month: '4月', uv: 278, pv: 390, amt: 278 },
- { month: '5月', uv: 189, pv: 480, amt: 189 },
+ {
+ month: '1月',
+ uv: 400,
+ pv: 240,
+ amt: 240,
+ },
+ {
+ month: '2月',
+ uv: 300,
+ pv: 456,
+ amt: 300,
+ },
+ {
+ month: '3月',
+ uv: 500,
+ pv: 139,
+ amt: 200,
+ },
+ {
+ month: '4月',
+ uv: 278,
+ pv: 390,
+ amt: 278,
+ },
+ {
+ month: '5月',
+ uv: 189,
+ pv: 480,
+ amt: 189,
+ },
];
const pieData = [
- { name: 'Vue', value: 40 },
- { name: 'React', value: 35 },
- { name: 'Angular', value: 25 },
+ {
+ name: 'Vue',
+ value: 40,
+ },
+ {
+ name: 'React',
+ value: 35,
+ },
+ {
+ name: 'Angular',
+ value: 25,
+ },
];
return (
-