Przeglądaj źródła

✨ feat(FinancialDashboard): 实现3D柱状图可视化效果

- 创建ThreeDBar组件,实现自定义3D柱状图SVG渲染
- 替换原有的普通柱状图为3D立体柱状图,提升视觉层次感
- 移除旧的线性渐变定义,采用3D效果的多图层渐变设计
- 优化坐标系转换,确保3D图形在不同尺寸下正确显示
yourname 2 miesięcy temu
rodzic
commit
9f347adc79

+ 54 - 9
src/client/home/pages/FinancialDashboard/components/IncomeMetrics.tsx

@@ -21,6 +21,59 @@ const chartData = incomeData.map(item => ({
   '收入': item.income
   '收入': item.income
 }));
 }));
 
 
+// 自定义 3D 柱状图组件 - 基于提供的SVG设计
+const ThreeDBar = (props: any) => {
+  const { x, y, width, height } = props;
+
+  // 将Recharts的坐标系转换为SVG的坐标系
+  const svgWidth = 80;
+  const svgHeight = 254;
+  const scaleX = width / svgWidth;
+  const scaleY = height / svgHeight;
+
+  return (
+    <g transform={`translate(${x},${y}) scale(${scaleX},${scaleY})`}>
+      <path d="M40.5 252H80L80 3L40.5 3L40.5 252Z" fill="url(#paint0_linear_1977_58682)"/>
+      <rect width="1" height="249" transform="matrix(-1 0 0 1 40.5 3)" fill="url(#paint1_linear_1977_58682)"/>
+      <path d="M0 252H39.5L39.5 3L0 3L0 252Z" fill="url(#paint2_linear_1977_58682)"/>
+      <path d="M80 251.998L40 254L0 251.998L40 249.667L80 251.998Z" fill="url(#paint3_linear_1977_58682)" fillOpacity="0.6"/>
+      <path d="M40.5 248.5H39.5V253.5H40.5V248.5Z" fill="url(#paint4_linear_1977_58682)"/>
+      <path d="M40 0L80 2.99636L40 6L0 2.99636L40 0Z" fill="url(#paint5_linear_1977_58682)"/>
+      <path d="M80 3C73.1703 3.36748 66.4401 3.78174 59.7099 4.20267C56.3282 4.40312 53.0128 4.63697 49.6643 4.85746L39.6187 5.52561H40.3813L30.3357 4.85746C26.9872 4.63697 23.6718 4.40312 20.2901 4.20267C13.5599 3.78174 6.82967 3.36748 0 3C6.49814 3.54788 13.0957 4.049 19.6933 4.54343C22.9755 4.79733 26.3241 5.0245 29.6395 5.25835L39.6187 5.96659L40.0166 6L40.3813 5.97327L50.3605 5.26503C53.6759 5.0245 57.0245 4.80401 60.3067 4.54343C66.9043 4.049 73.5019 3.54788 80 3Z" fill="url(#paint6_linear_1977_58682)"/>
+      <defs>
+        <linearGradient id="paint0_linear_1977_58682" x1="60.2589" y1="251.458" x2="60.2589" y2="3.00841" gradientUnits="userSpaceOnUse">
+          <stop stopColor="#FF8A00" stopOpacity="0.2"/>
+          <stop offset="1" stopColor="#FFD600"/>
+        </linearGradient>
+        <linearGradient id="paint1_linear_1977_58682" x1="0.5" y1="0" x2="0.5" y2="249" gradientUnits="userSpaceOnUse">
+          <stop stopColor="#FEFFC2"/>
+          <stop offset="1" stopColor="#FF9900" stopOpacity="0.3"/>
+        </linearGradient>
+        <linearGradient id="paint2_linear_1977_58682" x1="19.7589" y1="251.069" x2="19.7589" y2="3.00843" gradientUnits="userSpaceOnUse">
+          <stop offset="0.00462963" stopColor="#FF8A00" stopOpacity="0.2"/>
+          <stop offset="1" stopColor="#FFB800"/>
+        </linearGradient>
+        <linearGradient id="paint3_linear_1977_58682" x1="40" y1="249.667" x2="40" y2="254" gradientUnits="userSpaceOnUse">
+          <stop stopColor="#58370F"/>
+          <stop offset="1" stopColor="#A9600F"/>
+        </linearGradient>
+        <linearGradient id="paint4_linear_1977_58682" x1="39.5" y1="248.885" x2="39.5" y2="253.885" gradientUnits="userSpaceOnUse">
+          <stop stopColor="#715120"/>
+          <stop offset="1" stopColor="#8D7340" stopOpacity="0"/>
+        </linearGradient>
+        <linearGradient id="paint5_linear_1977_58682" x1="39.9937" y1="5.9965" x2="39.9937" y2="0" gradientUnits="userSpaceOnUse">
+          <stop stopColor="#FCFF6C"/>
+          <stop offset="1" stopColor="#FF8A00"/>
+        </linearGradient>
+        <linearGradient id="paint6_linear_1977_58682" x1="40.0103" y1="5.99719" x2="40.0103" y2="2.5" gradientUnits="userSpaceOnUse">
+          <stop stopColor="white"/>
+          <stop offset="1" stopColor="white" stopOpacity="0.3"/>
+        </linearGradient>
+      </defs>
+    </g>
+  );
+};
+
 export function IncomeMetrics({ className }: IncomeMetricsProps) {
 export function IncomeMetrics({ className }: IncomeMetricsProps) {
   return (
   return (
     <div className={`h-[480px] overflow-clip relative shrink-0 w-full ${className || ''}`}>
     <div className={`h-[480px] overflow-clip relative shrink-0 w-full ${className || ''}`}>
@@ -85,17 +138,9 @@ export function IncomeMetrics({ className }: IncomeMetricsProps) {
                 />
                 />
                 <Bar
                 <Bar
                   dataKey="收入"
                   dataKey="收入"
-                  fill="url(#incomeGradient)"
-                  radius={[2, 2, 0, 0]}
+                  shape={<ThreeDBar />}
                   barSize={35}
                   barSize={35}
                 />
                 />
-                <defs>
-                  {/* 收入渐变 - 匹配BarElement的蓝色渐变 */}
-                  <linearGradient id="incomeGradient" x1="0" y1="0" x2="0" y2="1">
-                    <stop offset="0%" stopColor="#a2beff" stopOpacity={0.8}/>
-                    <stop offset="100%" stopColor="#a2beff" stopOpacity={0}/>
-                  </linearGradient>
-                </defs>
               </BarChart>
               </BarChart>
             </ResponsiveContainer>
             </ResponsiveContainer>
           </div>
           </div>