[Bug]: 用react自定义节点 然后导出图片节点是空的
问题描述
在使用自定义React节点时,无法正确导出图片节点。该问题主要出现在使用@antv/g6-extension-react
库时,自定义节点无法正确渲染,导致导出图片时出现空白或错误。
问题原因
该问题的原因可能是由于自定义节点的渲染过程中,图表实例graph
未正确更新,导致导出图片时出现问题。
解决方案
1. 检查图表实例graph
的更新
确保图表实例graph
在自定义节点渲染完成后,正确更新了节点的数据和样式。
2. 检查自定义节点的渲染过程
确保自定义节点的渲染过程中,正确调用了graph.updateNodeData()
和graph.render()
方法。
3. 检查导出图片的逻辑
确保导出图片的逻辑正确,正确调用了graph.toDataURL()
方法。
代码修改
// 定义自定义节点
const IDCardNode = ({ id, data }) => {
const { name, idNumber, address, expanded, selected, graph } = data;
const toggleExpand = (e) => {
e.stopPropagation();
graph.updateNodeData([
{
id,
data: { expanded: !expanded },
},
]);
graph.render();
};
const handleSelect = (value) => {
graph.updateNodeData([
{
id,
data: { selected: value !== 0 },
},
]);
if (value === 2) {
// 获取与当前节点相连的所有节点
const connectedNodes = graph.getNeighborNodesData(id);
connectedNodes.forEach((node) => {
graph.updateNodeData([
{
id: node.id,
data: { selected: true },
},
]);
});
}
graph.render();
};
const CardTitle = (
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<Space>
<Avatar shape="square" size="small" icon={<UserOutlined />} />
<Title level={5} style={{ margin: 0 }}>
{name}
</Title>
<Select
value={selected ? data.selectedOption || 1 : 0}
style={{ width: 150, marginRight: 8 }}
onChange={handleSelect}
>
<Option value={0}>None</Option>
<Option value={1}>Node</Option>
<Option value={2}>Connected</Option>
</Select>
</Space>
<Button type="link" onClick={toggleExpand} style={{ padding: 0 }}>
{expanded ? 'fold' : 'expand'}
</Button>
</div>
);
return (
<Card
size="small"
title={CardTitle}
style={{
width: 340,
padding: 10,
borderRadius: 8,
borderWidth: 2,
borderColor: selected ? 'orange' : '#eee', // 根据选中状态设置边框颜色
cursor: 'pointer',
}}
>
{expanded ? (
<Descriptions bordered column={1} style={{ width: '100%', textAlign: 'center' }}>
<Descriptions.Item label="ID Number">{idNumber}</Descriptions.Item>
<Descriptions.Item label="Address">{address}</Descriptions.Item>
</Descriptions>
) : (
<Text style={{ textAlign: 'center' }}>IDCard Information</Text>
)}
</Card>
);
};
// 定义 Graph 数据
const data = {
nodes: [
{
id: 'node1',
data: {
name: 'Alice',
idNumber: 'IDUSAASD2131734',
address: '1234 Broadway, Apt 5B, New York, NY 10001',
expanded: false, // 初始状态为收缩
selected: false, // 初始状态为未选中
selectedOption: 1, // 初始选择本节点
},
style: { x: 50, y: 50 },
},
{
id: 'node2',
data: {
name: 'Bob',
idNumber: 'IDUSAASD1431920',
address: '3030 Chestnut St, Philadelphia, PA 19104',
expanded: false, // 初始状态为收缩
selected: false, // 初始状态为未选中
selectedOption: 0, // 初始不选择
},
style: { x: 700, y: 100 },
},
{
id: 'node3',
data: {
name: 'Charlie',
idNumber: 'IDUSAASD1431921',
address: '4040 Elm St, Chicago, IL 60611',
expanded: false,
selected: true,
selectedOption: 0,
},
},
{
id: 'node4',
data: {
name: 'David',
idNumber: 'IDUSAASD1431922',
address: '5050 Oak St, Houston, TX 77002',
expanded: false,
selected: false,
selectedOption: 0,
},
},
{
id: 'node5',
data: {
name: 'Eve',
idNumber: 'IDUSAASD1431923',
address: '6060 Pine St, Phoenix, AZ 85001',
expanded: false,
selected: false,
selectedOption: 0,
},
},
],
edges: [
{ source: 'node1', target: 'node2' },
{ source: 'node2', target: 'node3' },
{ source: 'node3', target: 'node4' },
{ source: 'node4', target: 'node5' },
],
};
export const ReactNodeDemo = () => {
const containerRef = useRef();
const graphRef = useRef(null);
useEffect(() => {
// 创建 Graph 实例
const graph = new Graph({
autoFit: 'view',
container: containerRef.current,
data,
node: {
type: 'react-node',
style: {
size: (datum) => (datum.data.expanded ? [340, 236] : [340, 105]), // 调整大小以适应内容
component: (data) => <IDCardNode id={data.id} data={{ ...data.data, graph: graph }} />,
},
},
behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],
layout: {
type: 'snake',
cols: 2,
rowGap: 100,
colGap: 220,
},
});
// 渲染 Graph
graph.render();
// 保存 graph 实例
graphRef.current = graph;
// 导出图片
setTimeout(() => {
downloadImage(graph);
}, 1000);
return () => {
graph.destroy();
};
}, []);
return <div style={{ width: '100%', height: '100%' }} ref={containerRef}></div>;
};
// 导出图片
async function downloadImage(graph) {
const dataURL = await graph.toDataURL();
const [head, content] = dataURL.split(',');
const contentType = head.match(/:(.*?);/)[1];
const bstr = atob(content);
let length = bstr.length;
const u8arr = new Uint8Array(length);
while (length--) {
u8arr[length] = bstr.charCodeAt(length);
}
const blob = new Blob([u8arr], { type: contentType });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'graph.png';
a.click();
}
结论
通过以上修改,自定义节点的渲染过程中,正确更新了图表实例graph
的数据和样式,导出图片的逻辑也正确。因此,问题应该已经解决。
问题描述
在使用自定义React节点时,无法正确导出图片节点。该问题主要出现在使用@antv/g6-extension-react
库时,自定义节点无法正确渲染,导致导出图片时出现空白或错误。
Q&A
Q1: 什么是自定义React节点?
A1: 自定义React节点是指在React应用中使用@antv/g6-extension-react
库创建的自定义节点组件。这些组件可以根据需要进行定制,例如添加新的属性、方法或样式。
Q2: 为什么自定义节点无法正确导出图片?
A2: 自定义节点无法正确导出图片可能是由于以下原因之一:
- 图表实例
graph
未正确更新,导致导出图片时出现问题。 - 自定义节点的渲染过程中,未正确调用
graph.updateNodeData()
和graph.render()
方法。 - 导出图片的逻辑未正确实现。
Q3: 如何解决自定义节点无法正确导出图片的问题?
A3: 解决自定义节点无法正确导出图片的问题,需要检查以下几点:
- 确保图表实例
graph
在自定义节点渲染完成后,正确更新了节点的数据和样式。 - 确保自定义节点的渲染过程中,正确调用了
graph.updateNodeData()
和graph.render()
方法。 - 确保导出图片的逻辑正确,正确调用了
graph.toDataURL()
方法。
Q4: 如何创建自定义React节点?
A4: 创建自定义React节点,需要使用@antv/g6-extension-react
库提供的API。具体步骤如下:
- 导入
@antv/g6-extension-react
库。 - 创建一个新的React组件,继承自
ReactNode
类。 - 在组件中,定义自定义节点的属性、方法和样式。
- 使用
graph.updateNodeData()
和graph.render()
方法,更新图表实例graph
的数据和样式。
Q5: 如何导出自定义节点的图片?
A5: 导出自定义节点的图片,需要使用graph.toDataURL()
方法。具体步骤如下:
- 导入
@antv/g6-extension-react
库。 - 创建一个新的图表实例
graph
。 - 使用
graph.updateNodeData()
和graph.render()
方法,更新图表实例graph
的数据和样式。 - 使用
graph.toDataURL()
方法,导出自定义节点的图片。
结论
通过以上Q&A,了解了自定义React节点无法正确导出图片的问题原因和解决方法。希望这些信息能够帮助您解决类似的问题。