D3NodeArrows

Basic force directed layout with directional arrows

by Philippe Guglielmetti

HTML

<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
<script type="application/json" id="mis">
{"links": [{"target": 23, "source": 10}, {"target": 123, "source": 10}, {"target": 130, "source": 17}, {"target": 86, "source": 31}, {"target": 95, "source": 31}, {"target": 18, "source": 31}, {"target": 3, "source": 31}, {"target": 115, "source": 31}, {"target": 120, "source": 31}, {"target": 56, "source": 31}, {"target": 58, "source": 31}, {"target": 40, "source": 31}, {"target": 87, "source": 31}, {"target": 113, "source": 31}, {"target": 134, "source": 31}, {"target": 15, "source": 31}, {"target": 65, "source": 31}, {"target": 129, "source": 31}, {"target": 99, "source": 31}, {"target": 130, "source": 33}, {"target": 130, "source": 38}, {"target": 54, "source": 62}, {"target": 0, "source": 71}, {"target": 1, "source": 71}, {"target": 2, "source": 71}, {"target": 4, "source": 71}, {"target": 5, "source": 71}, {"target": 6, "source": 71}, {"target": 7, "source": 71}, {"target": 8, "source": 71}, {"target": 9, "source": 71}, {"target": 11, "source": 71}, {"target": 12, "source": 71}, {"target": 13, "source": 71}, {"target": 14, "source": 71}, {"target": 16, "source": 71}, {"target": 35, "source": 71}, {"target": 19, "source": 71}, {"target": 20, "source": 71}, {"target": 21, "source": 71}, {"target": 22, "source": 71}, {"target": 24, "source": 71}, {"target": 25, "source": 71}, {"target": 105, "source": 71}, {"target": 27, "source": 71}, {"target": 28, "source": 71}, {"target": 29, "source": 71}, {"target": 30, "source": 71}, {"target": 32, "source": 71}, {"target": 34, "source": 71}, {"target": 107, "source": 71}, {"target": 84, "source": 71}, {"target": 91, "source": 71}, {"target": 39, "source": 71}, {"target": 41, "source": 71}, {"target": 42, "source": 71}, {"target": 43, "source": 71}, {"target": 44, "source": 71}, {"target": 45, "source": 71}, {"target": 46, "source": 71}, {"target": 47, "source": 71}, {"target": 48, "source":...

CSS

.node {
  stroke: #fff;
  stroke-width: 1.5px;
}

.link {
  stroke: #999;
  stroke-opacity: .6;
}

d3-tip {
    line-height: 1;
    color: black;
}

JavaScript

//Constants for the SVG
var width = 1000,
  height = 1000;

//Set up the colour scale
var color = d3.scale.category20();

//Set up the force layout
var force = d3.layout.force()
  .charge(-120)
  .linkDistance(80)
  .size([width, height]);

//Append a SVG to the body of the html page. Assign this SVG as an object to svg
var svg = d3.select("body").append("svg")
  .attr("width", width)
  .attr("height", height);

//Read the data from the mis element 
var mis = document.getElementById('mis').innerHTML;
graph = JSON.parse(mis);

//Creates the graph data structure out of the json data
force.nodes(graph.nodes)
  .links(graph.links)
  .start();

//Create all the line svgs but without locations yet
var link = svg.selectAll(".link")
  .data(graph.links)
  .enter().append("line")
  .attr("class", "link")
  .style("marker-end", "url(#suit)") //Added 
;

//Do the same with the circles for the nodes - no 
var node = svg.selectAll(".node")
  .data(graph.nodes)
  .enter().append("circle")
  .attr("class", "node")
  .attr("r", 8)
  .style("fill", function(d) {
    return color(d.assignee);
  })
  .call(force.drag);
 .on('mouseover', tip.show) //Added
 .on('mouseout', tip.hide); //Added 
  
var padding = 1, // separation between circles
    radius=8;
function collide(alpha) {
  var quadtree = d3.geom.quadtree(graph.nodes);
  return function(d) {
    var rb = 2*radius + padding,
        nx1 = d.x - rb,
        nx2 = d.x + rb,
        ny1 = d.y - rb,
        ny2 = d.y + rb;
    quadtree.visit(function(quad, x1, y1, x2, y2) {
      if (quad.point && (quad.point !== d)) {
        var x = d.x - quad.point.x,
            y = d.y - quad.point.y,
            l = Math.sqrt(x * x + y * y);
          if (l < rb) {
          l = (l - rb) / l * alpha;
          d.x -= x *= l;
          d.y -= y *= l;
          quad.point.x += x;
          quad.point.y += y;
        }
      }
      return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
    });
  };
}

//Set up tooltip
var tip = d3.tip()
   ...