Я пытался работать с d3 js, чтобы создать динамический c график силы, который позволяет пользователю выполнять простую визуализацию. Всякий раз, когда эта функция restart2 () используется после перехода вперед / назад, я получаю дублированные элементы в моей DOM. Переход назад (который выталкивает наши элементы из массива данных), похоже, также не удаляет связи между узлами. Могу ли я узнать, где я ошибся?
function restart2() {
// Apply the general update pattern to the nodes.
node = svg.selectAll(".node").data(nodes);
node.exit().transition()
.attr("r", 0)
.remove();
node = node.enter()
.append("g")
.attr("class", "node").merge(node).call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
// .on("end", dragended) // only use this if you do not want the force to be dead after dragging
);
node.append("circle")
.attr("fill", function(d) { return color(d.id); })
.call(function(node) { node.transition().attr("r", 8); })
.merge(node).on("click", function(d) {
console.log(d);
alert("You clicked on node " + d.id);
});
node.append("title")
.text(function (d) {return d.id;});
//still testing the label for nodes which then has to be placed into the tick function
// svg.selectAll("text").remove();
texts = svg.selectAll(".node")
.data(nodes)
.enter()
.append("text")
.attr("dx", 590)
.attr("dy", 230)
.text(function(d) { return d.id; });
node.append("text")
.attr("x", 0)
.attr("dy", "20")
.attr("text-anchor", "middle")
.text(function (d) {return d.id;})
.on("click", function(d) {
newlabel = prompt("Please enter the new label:", d.id);
labels = document.getElementsByClassName("node");
// console.log(labels);
// console.log(labels[0].childNodes[2].innerHTML); //use this to navigate the dom for the node labels
for (i = 0; i < labels.length; i++){
// console.log(labels[i].childNodes[2].innerHTML);
if(labels[i].childNodes[2].innerHTML == d.id){
selectedlabel = labels[i]
}
}
// console.log(selectedlabel.childNodes[2].innerHTML);
selectedlabel.childNodes[2].innerHTML = newlabel;
});;
console.log("node.append text is completed");
//Handling links between nodes
console.log("starting to search for links");
link = svg.selectAll(".link").data(links);
link.exit().transition()
.attr("stroke-opacity", 0)
.attrTween("x1", function(d) { return function() { return d.source.x; }; })
.attrTween("x2", function(d) { return function() { return d.target.x; }; })
.attrTween("y1", function(d) { return function() { return d.source.y; }; })
.attrTween("y2", function(d) { return function() { return d.target.y; }; })
.remove();
link.enter()
.append("line")
.attr("class", "link")
.attr('marker-end','url(#arrowhead)')
.style("stroke", 'black');
link = svg.selectAll(".link");
link.enter().append("title")
.text(function (d) {return d.type;});
// Update and restart the simulation.
simulation.nodes(nodes).on("tick", ticked);
simulation.force("link").links(links);
simulation.alpha(1).restart();
}
// The tick handler is the function that enables you to get the state of the layout when
// it has changed (the simulation has advanced by a tick) and act on it.
function ticked() {
//get the layout for the nodes
node.attr("transform", function (d) {return "translate(" + d.x + ", " + d.y + ")";});
//get the layout for the links
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
//labelling for nodes
texts.attr("transform", function (d) {return "translate(" + d.x + ", " + d.y + ")";});
}