pref: src/views/LimitAnalyse 页面 "数据分析"卡片中的"热词云图" 依赖更新
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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 (
|
||||
<Center h="400px">
|
||||
@@ -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 (
|
||||
<ReactWordcloud
|
||||
<Box ref={containerRef} h="400px" w="100%">
|
||||
{dimensions.width > 0 && (
|
||||
<svg width={dimensions.width} height={dimensions.height}>
|
||||
<Wordcloud
|
||||
words={words}
|
||||
options={options}
|
||||
callbacks={callbacks}
|
||||
/>
|
||||
width={dimensions.width}
|
||||
height={dimensions.height}
|
||||
fontSize={fontSizeSetter}
|
||||
font="Microsoft YaHei, sans-serif"
|
||||
padding={3}
|
||||
spiral="archimedean"
|
||||
rotate={0}
|
||||
random={() => 0.5}
|
||||
>
|
||||
{(cloudWords) =>
|
||||
cloudWords.map((w, i) => (
|
||||
<VisxText
|
||||
key={w.text}
|
||||
fill={WORDCLOUD_COLORS[i % WORDCLOUD_COLORS.length]}
|
||||
textAnchor="middle"
|
||||
transform={`translate(${w.x}, ${w.y}) rotate(${w.rotate})`}
|
||||
fontSize={w.size}
|
||||
fontFamily={w.font}
|
||||
fontWeight="bold"
|
||||
>
|
||||
{w.text}
|
||||
</VisxText>
|
||||
))
|
||||
}
|
||||
</Wordcloud>
|
||||
</svg>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user