imetting/frontend/src/components/MindMap.jsx

65 lines
2.2 KiB
React
Raw Normal View History

2026-03-26 06:55:12 +00:00
import React, { useEffect, useRef, useState } from 'react';
import { Transformer } from 'markmap-lib';
import { Markmap } from 'markmap-view';
2026-03-26 06:55:12 +00:00
import { Spin, Empty, Button, Space } from 'antd';
import { FullscreenOutlined, ZoomInOutlined, ZoomOutOutlined, SyncOutlined } from '@ant-design/icons';
2026-03-26 06:55:12 +00:00
const transformer = new Transformer();
2026-03-26 06:55:12 +00:00
const MindMap = ({ content, title }) => {
const svgRef = useRef(null);
const markmapRef = useRef(null);
2026-03-26 06:55:12 +00:00
const [loading, setLoading] = useState(true);
useEffect(() => {
2026-03-26 06:55:12 +00:00
if (!content || !svgRef.current) return;
2026-03-26 06:55:12 +00:00
setLoading(true);
try {
2026-03-26 06:55:12 +00:00
const { root } = transformer.transform(content);
if (markmapRef.current) {
markmapRef.current.setData(root);
2026-03-26 06:55:12 +00:00
markmapRef.current.fit();
} else {
2026-03-26 06:55:12 +00:00
markmapRef.current = Markmap.create(svgRef.current, {
autoFit: true,
duration: 500,
}, root);
}
} catch (error) {
2026-03-26 06:55:12 +00:00
console.error('Markmap error:', error);
} finally {
setLoading(false);
}
2026-03-26 06:55:12 +00:00
}, [content]);
2026-03-26 06:55:12 +00:00
const handleFit = () => markmapRef.current?.fit();
const handleZoomIn = () => markmapRef.current?.rescale(1.2);
const handleZoomOut = () => markmapRef.current?.rescale(0.8);
2026-03-26 06:55:12 +00:00
if (!content) return <Empty description="暂无内容,无法生成思维导图" />;
return (
2026-03-26 06:55:12 +00:00
<div className="mindmap-container" style={{ position: 'relative', width: '100%', height: '100%', minHeight: 500 }}>
{loading && (
<div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 10, background: 'rgba(255,255,255,0.8)' }}>
<Spin tip="生成导图中..." />
</div>
)}
<div style={{ position: 'absolute', right: 16, top: 16, zIndex: 20 }}>
<Space direction="vertical">
<Button icon={<FullscreenOutlined />} onClick={handleFit} title="自适应" />
<Button icon={<ZoomInOutlined />} onClick={handleZoomIn} title="放大" />
<Button icon={<ZoomOutOutlined />} onClick={handleZoomOut} title="缩小" />
</Space>
</div>
2026-03-26 06:55:12 +00:00
<svg ref={svgRef} style={{ width: '100%', height: '100%', minHeight: 500 }} />
</div>
);
};
export default MindMap;