![](/img/trans.png)
[英]React + D3 + Force-Directed Tree + Adjustable Link Strength
[英]Update d3's force-directed graph in a React app while preserving old nodes positions
我正在使用 d3 的forceSimulation
來計算給定力的每個節點的 (x,y) 坐標(從沒有節點或鏈接開始):
const simulation = d3.forceSimulation()
.force('charge', d3.forceManyBody().strength(-1000))
.force('link', d3.forceLink().id(d => d?.id).distance(200))
.force('collide', d3.forceCollide().radius(150))
.stop()
.tick(300)
然后聽simulation
的 'tick' 事件來更新圖形(使用 react-flow-renderer setNodes
和setSetEdges
見文檔):
simulation.on('tick', () => {
setEdges([...simulation.force('link').links()].map(setEdge));
setNodes([...simulation.nodes()].map(setNode));
})
React 部分應該在將實際nodes
和edges
應用於simulation
simulation
useEffect(() => {
simulation.nodes(nodes);
simulation.force('link').links(edges);
simulation.alpha(0.1).restart();
return () => simulation.stop();
}, [nodes, edges])
現在, nodes
和edges
可能會更新,因為有可能擴展節點的關系。 問題是 - 每次我們擴展節點關系時,我們都會得到一個新的節點和邊數組,每個包含舊值和新值:
虛擬示例:
old nodes: [{ id: 1 }]
new nodes: [{ id: 1 }, { id: 2}, { id: 3}]
“模擬”以新值重新啟動並從頭開始重新計算圖形,因此新圖形與舊圖形完全不同。 是否有一個選項可以使圖形保留舊節點的(x,y)坐標並簡單地將新節點“添加”到現有圖形中?
如果有人遇到這種問題:
在更新節點的數組之前記錄以前的節點:
const prev = usePrev(new Map(nodes.map((node) => [node.id, node])));
然后,在將新節點傳遞給模擬之前,制作一個新副本,合並以前存在的元素,如下所示:
useEffect(() => {
nodes = nodes.map((node) => Object.assign(node, prev?.get(node.id)));
simulation.nodes(nodes);
(...) // rest of the code
這樣,當模擬從新節點開始時,其中一些可能已經設置了 (x,y) 坐標。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.