我想在点击节点时以新的节点和边缘更新有向图。 我从这个例子https://bl.ocks.org/mbostock/1095795开始 但目前我不知道如何处理奇怪定位的新边(和箭头)。 https://jsfiddle.net/alfredopacino/z1ppabL0/
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
color = d3.scaleOrdinal(d3.schemeCategory10);
var a = {id: "1"},
b = {id: "2"},
c = {id: "3"},
nodes = [a, b, c],
links = [],
NODE_CNT = nodes.length; //the nodes count so long
links.push({source: a, target: b}); // Add a-b.
links.push({source: b, target: c}); // Add b-c.
links.push({source: c, target: a}); // Add c-a.
var simulation = d3.forceSimulation(nodes)
.force("charge", d3.forceManyBody().strength(-1000))
.force("link", d3.forceLink(links).distance(200))
.force("x", d3.forceX())
.force("y", d3.forceY())
.alphaTarget(1)
.on("tick", ticked);
var g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"),
link = g.append("g").attr("stroke", "#000").attr("stroke-width", 1.5).selectAll(".link");
// build the arrow.
svg.append("svg:defs").selectAll("marker")
.data(["end"]) // Different link/path types can be defined here
.enter().append("svg:marker") // This section adds in the arrows
.attr("id", String)
.attr("viewBox", "0 -5 10 10")
.attr("refX", 15)
.attr("refY", -1.5)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5");
var node = g.append("g").attr("stroke", "#fff").attr("stroke-width", 1.5).selectAll(".node");
update();
function update() {
// Apply the general update pattern to the nodes.
node = node.data(nodes, function (d) {
return d.id;
});
node.exit().remove();
node = node.enter().append("circle").attr("fill", function (d) {
return color(d.id);
}).attr("r", 8).merge(node);
node.on("click", addNodeAndEdges);
// Apply the general update pattern to the links.
link = link.data(links, function (d) {
return d.source.id + "-" + d.target.id;
});
link.exit().remove();
link = link.enter().append("line").merge(link)
.attr("marker-end", "url(#end)"); //-----------------arrow----------
// Update and restart the simulation.
simulation.nodes(nodes);
simulation.force("link").links(links);
simulation.alpha(1).restart();
}
function ticked() {
node.attr("cx", function (d) {
return d.x;
})
.attr("cy", function (d) {
return d.y;
})
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;
});
}
function addNodeAndEdges(d) {
//select(d) references the data, not the element. You need to select(this)
console.log(this)
NODE_CNT++;
nodes.push({id: NODE_CNT});
links.push({source: {id: NODE_CNT}, target: {id: NODE_CNT - 1}});
links.push({source: {id: NODE_CNT - 2}, target: {id: NODE_CNT}});
d3.select(this).attr('r', 20)
.style("fill", "lightcoral")
.style("stroke", "red");
update();
}
答案 0 :(得分:1)
问题出在您的addNodeAndEdges
功能中。当您向nodes
和links
添加新元素时,您将创建新对象,而不是引用现有对象。例如,当您推送源{id: 1}
的链接时,这与源a
不同。当力模拟设置x
的{{1}}和y
属性时,新链接的源节点也不会更新。因此,您添加的新路径没有x和y坐标。
Here's a fiddle that fixes that,对a
中的现有对象使用一致引用。