From 39978c57d5bf8483698a6c3fb9f50ab27c811e00 Mon Sep 17 00:00:00 2001 From: zdl <3489966805@qq.com> Date: Fri, 21 Nov 2025 17:37:56 +0800 Subject: [PATCH] =?UTF-8?q?pref=EF=BC=9A=20src/views/LimitAnalyse=20?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=20"=E6=95=B0=E6=8D=AE=E5=88=86=E6=9E=90"?= =?UTF-8?q?=E5=8D=A1=E7=89=87=E4=B8=AD=E7=9A=84"=E7=83=AD=E8=AF=8D?= =?UTF-8?q?=E4=BA=91=E5=9B=BE"=20=E4=BE=9D=E8=B5=96=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 5 +- .../components/DataVisualizationComponents.js | 98 ++++++++++++++----- 2 files changed, 78 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index f339a183..f6d45165 100755 --- a/package.json +++ b/package.json @@ -22,7 +22,11 @@ "@splidejs/react-splide": "^0.7.12", "@tanstack/react-virtual": "^3.13.12", "@tippyjs/react": "^4.2.6", + "@visx/responsive": "^3.12.0", + "@visx/scale": "^3.12.0", + "@visx/text": "^3.12.0", "@visx/visx": "^3.12.0", + "@visx/wordcloud": "^3.12.0", "antd": "^5.27.4", "apexcharts": "^3.27.3", "axios": "^1.10.0", @@ -70,7 +74,6 @@ "react-tagsinput": "3.19.0", "react-to-print": "^2.13.0", "react-tsparticles": "^2.12.2", - "react-wordcloud": "^1.2.7", "recharts": "^3.1.2", "sass": "^1.49.9", "scroll-lock": "^2.1.5", diff --git a/src/views/LimitAnalyse/components/DataVisualizationComponents.js b/src/views/LimitAnalyse/components/DataVisualizationComponents.js index 4c02148f..63163f5d 100644 --- a/src/views/LimitAnalyse/components/DataVisualizationComponents.js +++ b/src/views/LimitAnalyse/components/DataVisualizationComponents.js @@ -1,4 +1,4 @@ -import React, { useMemo, useState, useEffect } from 'react'; +import React, { useMemo, useState, useEffect, useRef } from 'react'; import { Box, Card, @@ -39,7 +39,6 @@ import { import { getFormattedTextProps } from '../../../utils/textUtils'; import { ExternalLinkIcon } from '@chakra-ui/icons'; import RiskDisclaimer from '../../../components/RiskDisclaimer'; -import './WordCloud.css'; import { BarChart, Bar, PieChart, Pie, Cell, @@ -51,15 +50,44 @@ import { Treemap, Area, AreaChart, } from 'recharts'; -import ReactWordcloud from 'react-wordcloud'; +import { Wordcloud } from '@visx/wordcloud'; +import { scaleLog } from '@visx/scale'; +import { Text as VisxText } from '@visx/text'; + // 颜色配置 const CHART_COLORS = [ '#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEEAD', '#D4A5A5', '#9B6B6B', '#E9967A', '#B19CD9', '#87CEEB' ]; -// 词云图组件 +// 词云颜色 +const WORDCLOUD_COLORS = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEEAD']; + +// 词云图组件(使用 @visx/wordcloud,兼容 React 18) const WordCloud = ({ data }) => { + const [dimensions, setDimensions] = useState({ width: 0, height: 400 }); + const containerRef = useRef(null); + + // 监听容器尺寸变化 + useEffect(() => { + if (!containerRef.current) return; + + const updateDimensions = () => { + if (containerRef.current) { + setDimensions({ + width: containerRef.current.offsetWidth, + height: 400 + }); + } + }; + + updateDimensions(); + const resizeObserver = new ResizeObserver(updateDimensions); + resizeObserver.observe(containerRef.current); + + return () => resizeObserver.disconnect(); + }, []); + if (!data || data.length === 0) { return (
@@ -75,29 +103,51 @@ const WordCloud = ({ data }) => { value: item.value || item.count || 1 })); - const options = { - rotations: 2, - rotationAngles: [-90, 0], - fontFamily: 'Microsoft YaHei, sans-serif', - fontSizes: [16, 80], - fontWeight: 'bold', - padding: 3, - scale: 'sqrt', - }; + // 计算字体大小比例 + const fontScale = scaleLog({ + domain: [ + Math.min(...words.map(w => w.value)), + Math.max(...words.map(w => w.value)) + ], + range: [16, 80], + }); - const callbacks = { - getWordColor: () => { - const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEEAD']; - return colors[Math.floor(Math.random() * colors.length)]; - } - }; + const fontSizeSetter = (datum) => fontScale(datum.value); return ( - + + {dimensions.width > 0 && ( + + 0.5} + > + {(cloudWords) => + cloudWords.map((w, i) => ( + + {w.text} + + )) + } + + + )} + ); };