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)
}
添加回答
举报