Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to increase the length of a link in D3 force layout

How can I increase the link length of a force graph. My code is written below. What should i change?

Also I want to label the "only child nodes" on mouse-over and the parent node has their label.

<!DOCTYPE html>
<html>
  <head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Force</title>
    <style type="text/css">

circle.node {
  cursor: pointer;
  stroke: #3182bd;
  stroke-width: 1.5px;
}

line.link {
  fill: none;
  stroke: #9ecae1;
  stroke-width: 1.5px;
}

    </style>
  </head>
  <body>
    <div id="chart"></div>
    <script src="../d3/d3.v3.min.js"></script>
    <script type="text/javascript">

var w = 960,
    h = 500,
    node,
    link,
    root;

var force = d3.layout.force()
    .on("tick", tick)
    .size([w*2, h*2]);

var vis = d3.select("#chart").append("svg:svg")
    .attr("width", w*2)
    .attr("height", h*2);

var diagonal = d3.svg.diagonal.radial()
    .projection(function(d) { return [d.y, d.x / (180) * Math.PI]; });
d3.json("try.json", function(json) {
  root = json;
  update();
});

function update() {
  var nodes = flatten(root),
      links = d3.layout.tree().links(nodes);

  // Restart the force layout.
  root.fixed=true;
  root.x=900;
  root.y=500;
  force
      .nodes(nodes)
      .links(links)
      .start();

  // Update the links…
  link = vis.selectAll("line.link")
      .data(links, function(d) { return d.target.id; });

  // Enter any new links.
  link.enter().insert("svg:line", ".node")
      .attr("class", "link")
      .attr("x1", function(d) { return d.source.x+100; })
      .attr("y1", function(d) { return d.source.y+100; })
      .attr("x2", function(d) { return d.target.x+100; })
      .attr("y2", function(d) { return d.target.y+100; });

  // Exit any old links.
  link.exit().remove();

  // Update the nodes…
  node = vis.selectAll("circle.node")
      .data(nodes, function(d) { return d.id; })
      .style("fill", color);

  // Enter any new nodes.
  node.enter().append("svg:circle")
      .attr("class", "node")
      .attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; })
      .attr("r", function(d) { return Math.sqrt(d.size) / 10 || 25; })
      .style("fill", color)
      .on("click", click)
      .call(force.drag);

  // Exit any old nodes.
  node.exit().remove();
}

function tick() {
  link.attr("x1", function(d) { return d.source.x-100; })
      .attr("y1", function(d) { return d.source.y; })
      .attr("x2", function(d) { return d.target.x-100; })
      .attr("y2", function(d) { return d.target.y; });

  node.attr("cx", function(d) { return d.x-100; })
      .attr("cy", function(d) { return d.y; });
}

// Color leaf nodes orange, and packages white or blue.
function color(d) {
  return d._children ? "#3182bd" : d.children ? "#c6dbef" : "#fd8d3c";
}

// Toggle children on click.
function click(d) {
  if (d.children) {
    d._children = d.children;
    d.children = null;
  } else {
    d.children = d._children;
    d._children = null;
  }
  update();
}

// Returns a list of all nodes under the root.
function flatten(root) {
  var nodes = [], i = 0;

  function recurse(node) {
    if (node.children) node.children.forEach(recurse);
    if (!node.id) node.id = ++i;
    nodes.push(node);
  }

  recurse(root);
  return nodes;
}

    </script>
  </body>
</html>   
like image 465
coder Avatar asked Jun 19 '13 06:06

coder


2 Answers

For the link distance, you can use link.distance.

Here is what the doc currently says about this function:

If distance is specified, sets the distance accessor to the specified number or function, re-evaluates the distance accessor for each link, and returns this force. If distance is not specified, returns the current distance accessor, which defaults to:

function distance() {
    return 30;
}

The distance accessor is invoked for each link, being passed the link and its zero-based index. The resulting number is then stored internally, such that the distance of each link is only recomputed when the force is initialized or when this method is called with a new distance, and not on every application of the force.

For the labels, please ask another question.

like image 71
Christopher Chiche Avatar answered Oct 17 '22 16:10

Christopher Chiche


Here you can use .distance to set the disance or length of a link.

var forceLink = d3
    .forceLink().id(function (d) {
        return d.id;
    })
    .distance(function (d) {
        return GetNodeDefaults(d.label).linkDistance;
    })
    .strength(0.1);

var simulation = d3.forceSimulation()
    .force("link", forceLink)
    .force("charge", d3.forceManyBody().strength(function (d, i) {
        var a = i == 0 ? -2000 : -1000;
        return a;
    }).distanceMin(200).distanceMax(1000))
    .force("center", d3.forceCenter(width / 2, height / 2))
    .force("y", d3.forceY(0.01))
    .force("x", d3.forceX(0.01))
    .on("tick", ticked);

Ref Link: https://github.com/d3/d3-force/blob/master/README.md#link_distance

like image 5
Vishweshwaraiah K Avatar answered Oct 17 '22 14:10

Vishweshwaraiah K