1 回答

TA貢獻2037條經驗 獲得超6個贊
在D3中,如果您想獲得新的進入/更新/退出選擇,則必須再次執行數據連接。您的代碼中發生的情況是:
您在函數中執行一次數據連接
initialize
(對于每個圖表元素)。該數據連接將每個節點標記為新節點并返回每個節點,然后您可以緩存這些結果。在您的
update
函數中,您每次都使用這些緩存的結果。
update
相反,每次圖形更改時,請在 上執行數據連接,而不是在 上執行initialize
。一個例子nodeElements
:
private initializeGraph(): void {
const mainGroup = select(this.svgElement.current)
.append("g")
.attr("id", "main");
// append nodes svg group
this.nodeElements = mainGroup.append("g")
.attr("id", "nodes")
}
private updateGraph(): void {
// select nodes & edges
const graphNodes = this.nodeElements
.selectAll<SVGCircleElement, Node>(".directed-graph-node")
.data<Node>(this.state.g.nodes, _ => _.id);
// update nodes with their current position
graphNodes.attr("cx", node => node.x)
.attr("cy", node => node.y);
// add newly added nodes if any
graphNodes.enter()
.append("circle")
.attr("class", ".directed-graph-node")
.attr("stroke", "steelblue")
.attr("cx", node => node.x)
.attr("cy", node => node.y)
.attr("r", 2.5)
.call(drag<SVGCircleElement, Node>());
// remove nodes that don't exist anymore
graphNodes.exit().remove();
}
正如您所看到的,這種模式相當嚴厲。我們可以使用Selection.join()來代替。它允許我們刪除enter和上的重復代碼update并減輕重量。
private updateGraph(): void {
const graphNodes = this.nodeElements
.selectAll<SVGCircleElement, Node>(".directed-graph-node")
// data() join()
.data<Node>(this.state.g.nodes, _ => _.id)
.join(
enter => enter.append("circle")
.attr("class", ".directed-graph-node")
.attr("stroke", "steelblue")
.attr("r", 2.5)
.call(drag<SVGCircleElement, Node>()),
update => update,
exit => exit.remove();
)
// enter + update past this point
.attr("cx", node => node.x)
.attr("cy", node => node.y)
}
添加回答
舉報