我正在尝试制作一个力导向图,其中根据需要添加和删除节点和链接。但是,虽然该图表使用添加/删除的链接和节点正确更新,但是所有旧节点仍然可见。
这是更新功能。我尝试了各种教程,重新排列了代码,再次检查了要更新的数据是否正确(即this.dataNodes正在变异,但是完全替换对象也不起作用),等等。老实说,我不知道什么我应该再找。
// ADDING LINKS
this.link = this.linkGroup.selectAll("path")
.data(this.dataLinks, (link) => {
return link.target.id + link.source.id
});
this.link.exit().remove();
const linkEnter = this.link.enter()
.append("path")
.attr("stroke-width", 2)
.style("stroke", "#ccc")
.style('marker-start', (d) => d.sync ? 'url(#start-arrow)' : '')
.style('marker-end', (d) => 'url(#end-arrow)');
this.link = linkEnter.merge(this.link);
// ADDING NODES
this.node = this.nodeGroup.selectAll(".nodes")
.data(this.dataNodes, function (node) { return node.id });
this.node.exit().remove();
const nodeEnter = this.node.enter()
.append("g")
.call(this.dragAndDrop);
// Main circle
nodeEnter.append("circle")
.attr("r", 10)
.attr("fill", "grey")
// ADDING CHARACTER NAMES
nodeEnter.append("text")
.attr("x", 12)
.attr("dy", ".35em")
.text(function (d) {return d.title;});
this.node = nodeEnter.merge(this.node);
this.simulation.nodes(this.dataNodes).on("tick", this.tickActions );
this.simulation.force('link').links(this.dataLinks);
this.simulation.alphaTarget(1).restart();
编辑: 首次创建力图时将调用此代码。 this.updateSimulation是上面的函数,并且没有问题。再次调用它,所有先前创建的节点都保留在图中。
this.svg = d3.select('#relationship-chart')
.append('svg')
.attr('width', this.width)
.attr('height', this.height);
// GROUPS
this.linkGroup = this.svg.append("g").attr("class", "links");
this.nodeGroup = this.svg.append("g").attr("class", "nodes");
// MAIN SIMULATION
this.link_force = d3.forceLink()
.id(function(d) { return d.id; })
.distance(100);
this.simulation = d3.forceSimulation()
.force("link", this.link_force)
.force("charge", d3.forceManyBody().strength(-200))
.force('center', d3.forceCenter(this.width / 2, this.height / 2))
//.force('collide', d3.forceCollide(25))
.force("x", d3.forceX())
.force("y", d3.forceY())
.alphaTarget(1);
// MISC DEFINTIONS
this.dragAndDrop = d3.drag()
.on("start", this.dragstarted)
.on("drag", this.dragged)
.on("end", this.dragended);
// ADDING ARROWS
this.svg.append('svg:defs').append('svg:marker')
.attr('id', 'end-arrow')
.attr('viewBox', '0 -5 10 10')
.attr('refX', 7)
.attr('markerWidth', 4)
.attr('markerHeight', 4)
.attr('orient', 'auto')
.append('svg:path')
.attr('d', 'M0,-5L10,0L0,5')
.attr('fill', '#ccc');
this.svg.append('svg:defs').append('svg:marker')
.attr('id', 'start-arrow')
.attr('viewBox', '0 -5 10 10')
.attr('refX', 1)
.attr('markerWidth', 4)
.attr('markerHeight', 4)
.attr('orient', 'auto')
.append('svg:path')
.attr('d', 'M10,-5L0,0L10,5')
.attr('fill', '#ccc');
this.updateSimulation();
答案 0 :(得分:2)
结果是我选择的是父元素类而不是子元素。我在创建的节点上添加了一个类,这消除了问题。
之前:
this.node = this.nodeGroup.selectAll(".nodes")
.data(this.dataNodes, function (node) { return node.id });
this.node.exit().remove();
const nodeEnter = this.node.enter()
.append("g")
.call(this.dragAndDrop);
之后:
this.node = this.nodeGroup.selectAll(".onenode")
.data(this.dataNodes, (node) => { return node.id });
this.node.exit().remove();
const nodeEnter = this.node.enter()
.append("g")
.attr("class", "onenode")
.call(this.dragAndDrop);