I want to remove node when click this node, so I just remove the node when click with nodes = nodes.filter(v => v.id !== d.id)
.Actually, it works at the first time, but it doesn't work next.
Here is my code:
uuid = function uuid() {
var template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
return template.replace(/[xy]/g, c => {
var r = (Math.random() * 16) | 0;
if (c === 'y') r = (r & 3) | 8;
return r.toString(16);
});
}
const width = 800;
const height = 400;
const count = 10;
let nodes = Array.from({length: count}).map((_, i) => ({x: width / count * i + 20, y: height / 2, id: uuid()}));
const svg = d3.select("svg").attr("viewBox", [0, 0, width, height]);
let node = svg
.selectAll(".node");
const simulation = d3
.forceSimulation()
.nodes(nodes)
.force("center", d3.forceCenter(width / 2, height / 2))
.stop();
function update() {
node = node.data(nodes, d=> d.id)
.join("g")
.append("circle")
.attr("r", 12)
.attr("cursor", "move")
.attr("fill", "#ccc")
.attr("stroke", "#000")
.attr("stroke-width", "1.5px")
.attr("transform", function (d) {return "translate(" + d.x + ", " + d.y + ")";})
.on("click", (ev, d) => {
nodes = nodes.filter(v => v.id !== d.id);
update();
});
simulation.nodes(nodes);
if (simulation.alpha() <= 1) {
simulation.alpha(1);
simulation.restart();
}
}
update()
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<svg></svg>
You only want to append a circle for the new nodes, for any other nodes, appending a circle means that the next time you click, there's actually two circles to remove, not one!
.join()
can be passed three functions, that you can apply to the enter
, update
, and exit
selections. These are executed, the return values are joined, and then you can do things to all selections combined.
In this case, I moved all the one-time circle
logic to the enter
part, being careful not to return the circle
, but the g
element that you first appended. If you return the circle
, it will combine these with the existing `g elements and the logic will break.
uuid = function uuid() {
var template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
return template.replace(/[xy]/g, c => {
var r = (Math.random() * 16) | 0;
if (c === 'y') r = (r & 3) | 8;
return r.toString(16);
});
}
const width = 800;
const height = 400;
const count = 10;
let nodes = Array.from({length: count}).map((_, i) => ({x: width / count * i + 20, y: height / 2, id: uuid()}));
const svg = d3.select("svg").attr("viewBox", [0, 0, width, height]);
let node = svg
.selectAll(".node");
const simulation = d3
.forceSimulation()
.nodes(nodes)
.force("center", d3.forceCenter(width / 2, height / 2))
.stop();
function update() {
console.log(nodes.length);
node = node.data(nodes, d=> d.id)
.join(
enter => {
const g = enter
.append("g")
.attr("class", "node");
g
.append("circle")
.attr("r", 12)
.attr("cursor", "move")
.attr("fill", "#ccc")
.attr("stroke", "#000")
.attr("stroke-width", "1.5px");
return g;
},
update => update,
exit => exit.remove()
)
.attr("transform", function (d) {return "translate(" + d.x + ", " + d.y + ")";})
.on("click", (ev, d) => {
nodes = nodes.filter(v => v.id !== d.id);
update();
});
simulation.nodes(nodes);
if (simulation.alpha() <= 1) {
simulation.alpha(1);
simulation.restart();
}
}
update()
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<svg></svg>