我已决定使用D3在React中创建交互式力定向图,但模拟开始后一切正常,但在React StrictMode中拖动不起作用,我认为这一定是由于在ReactStrict模式18中安装和重新安装组件,但我无法真正查明原因。
我使用效果挂钩的内容在哪里
useEffect(function () {
if (!svgRef.current) return;
const svg = d3.select(svgRef.current);
const nodes = d3.map(
props.nodes,
(node): Node => ({
...node,
})
);
const links = d3
.map(props.links, (link) => ({
source: nodes.find((node) => node.id === link.source),
target: nodes.find((node) => node.id === link.target),
}))
.filter(
(link): link is { source: Node; target: Node } =>
link.source !== undefined && link.target !== undefined
);
const simulation = d3
.forceSimulation(nodes)
.force(
"link",
d3
.forceLink(links)
.id((_, i) => nodes[i].id)
.distance(LINK_LENGHT)
)
.force("charge", d3.forceManyBody().strength(-NODE_REPULSION))
.force("center", d3.forceCenter())
.force("forceX", d3.forceX().strength(NODE_GRAVITY))
.force("forceY", d3.forceY().strength(NODE_GRAVITY))
.force("colide", d3.forceCollide(NODE_RADIUS * NODE_MARGIN))
.on("tick", ticked);
const link = svg
.selectAll("line")
.data(links)
.enter()
.append("line")
.style("stroke", "#aaa");
const node = svg
.selectAll("circle")
.data(nodes)
.enter()
.append("circle")
.call(
d3
.drag<SVGCircleElement, Node>()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended)
)
.attr("fill", (node) => node.color))
.attr("r", NODE_RADIUS)
.attr("stroke", "#000000")
.attr("stroke-width", 1);
function ticked() {
link
.attr("x1", (d) => d.source.x!)
.attr("y1", (d) => d.source.y!)
.attr("x2", (d) => d.target.x!)
.attr("y2", (d) => d.target.y!);
node.attr("cx", (d) => d.x!).attr("cy", (d) => d.y!);
}
function dragstarted(event: any, d: Node) {
if (!event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(event: any, d: Node) {
console.log(simulation.alpha());
d.fx = event.x;
d.fy = event.y;
}
function dragended(event: any, d: Node) {
if (!event.active) simulation.alphaTarget(0.0001);
d.fx = null;
d.fy = null;
}
},
[props.nodes.length, props.links.length]
)
任何线索或帮助都将不胜感激。
1条答案
按热度按时间ukdjmx9f1#
由于它在删除StrictMode后工作,我推测我需要在我的useEffect中有一个清理函数。结果我只需要删除我像这样插入的链接和节点。