简体   繁体   中英

Simple graph of nodes and links without using force layout

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM