How can I make a basic connected graph (two nodes and a link connecting them for example) that doesn't use a force()
layout? I just want to be able to drag a node and have the link adjust to stay connected as a node is being dragged. I dont want any of the charge or positioning capabilities of force()
. Essentially I want every node to be "sticky". Nodes will only move when being dragged.
But is there a simple way to do this? Every example I have seen is built around a force directed graph.
I've looked at this example, http://bl.ocks.org/mbostock/3750558 , but it starts with a force directed graph then makes the nodes sticky. This approach seems backwards for what I want.
Is there a basic example somewhere?
I have made a small code snippet. Hope this is helpful.
var data = { nodes: [{ name: "A", x: 200, y: 150 }, { name: "B", x: 140, y: 300 }, { name: "C", x: 300, y: 300 }, { name: "D", x: 300, y: 180 }], links: [{ source: 0, target: 1 }, { source: 1, target: 2 }, { source: 2, target: 3 }, ] }; var c10 = d3.scale.category10(); var svg = d3.select("body") .append("svg") .attr("width", 1200) .attr("height", 800); var drag = d3.behavior.drag() .on("drag", function(d, i) { dx += d3.event.dx dy += d3.event.dy d3.select(this).attr("cx", dx).attr("cy", dy); links.each(function(l, li) { if (l.source == i) { d3.select(this).attr("x1", dx).attr("y1", dy); } else if (l.target == i) { d3.select(this).attr("x2", dx).attr("y2", dy); } }); }); var links = svg.selectAll("link") .data(data.links) .enter() .append("line") .attr("class", "link") .attr("x1", function(l) { var sourceNode = data.nodes.filter(function(d, i) { return i == l.source })[0]; d3.select(this).attr("y1", sourceNode.y); return sourceNode.x }) .attr("x2", function(l) { var targetNode = data.nodes.filter(function(d, i) { return i == l.target })[0]; d3.select(this).attr("y2", targetNode.y); return targetNode.x }) .attr("fill", "none") .attr("stroke", "white"); var nodes = svg.selectAll("node") .data(data.nodes) .enter() .append("circle") .attr("class", "node") .attr("cx", function(d) { return dx }) .attr("cy", function(d) { return dy }) .attr("r", 15) .attr("fill", function(d, i) { return c10(i); }) .call(drag);
svg { background-color: grey; }
<script src="https://d3js.org/d3.v3.min.js"></script>
Gilsha has a great answer, but note that newer versions of d3 no longer use the behavior module.
Instead of this:
var drag = d3.behavior.drag()
.on("drag", function(d, i) {
d.x += d3.event.dx
d.y += d3.event.dy
d3.select(this).attr("cx", d.x).attr("cy", d.y);
links.each(function(l, li) {
if (l.source == i) {
d3.select(this).attr("x1", d.x).attr("y1", d.y);
} else if (l.target == i) {
d3.select(this).attr("x2", d.x).attr("y2", d.y);
}
});
});
Simply change d3.behavior.drag() to d3.drag()
var drag = d3.drag()
.on("drag", function(d, i) {
d.x += d3.event.dx
d.y += d3.event.dy
d3.select(this).attr("cx", d.x).attr("cy", d.y);
links.each(function(l, li) {
if (l.source == i) {
d3.select(this).attr("x1", d.x).attr("y1", d.y);
} else if (l.target == i) {
d3.select(this).attr("x2", d.x).attr("y2", d.y);
}
});
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.