d3.js self referencing links

forked

by Ram Tobolski

HTML

<!DOCTYPE html>
<body>
<script src="http://d3js.org/d3.v2.min.js?2.9.6"></script>
</body>

CSS

.link {
  stroke: #0f0;
  fill: none;
  stroke-width: 2px;
}

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

JavaScript

var width = 960,
    height = 500;

var color = d3.scale.category20();

var radius = d3.scale.sqrt()
    .range([0, 6]);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

var force = d3.layout.force()
    .size([width, height])
    .charge(-400)
    .linkDistance(function(d) { return radius(d.source.size) + radius(d.target.size) + 20; });

var graph = {
"nodes": [
    {"size": 12},
    {"size": 12},
    {"size": 12}
  ],
  "links": [
    {"source": 0, "target": 1},
    {"source": 1, "target": 2},
    {"source": 2, "target": 2}
  ]
};

var drawGraph = function(graph) {
  force
      .nodes(graph.nodes)
      .links(graph.links)
      .on("tick", tick)
      .start();
  var link = svg.selectAll(".link")
      .data(graph.links)
    .enter().append("path")
      .attr("class","link");

  var node = svg.selectAll(".node")
      .data(graph.nodes)
    .enter().append("g")
      .attr("class", "node")
      .call(force.drag);

  node.append("circle")
      .attr("r", function(d) { return radius(d.size); })
      .style("fill", function(d) { return color(d.atom); });

  function tick() {
    link.attr("d", function(d) {
      var x1 = d.source.x,
          y1 = d.source.y,
          x2 = d.target.x,
          y2 = d.target.y,
          dx = x2 - x1,
          dy = y2 - y1,
          dr = Math.sqrt(dx * dx + dy * dy),

          // Defaults for normal edge.
          drx = dr,
          dry = dr,
          xRotation = 0, // degrees
          largeArc = 0, // 1 or 0
          sweep = 1; // 1 or 0

          // Self edge.
          if ( x1 === x2 && y1 === y2 ) {
            // Fiddle with this angle to get loop oriented.
            xRotation = -45;

            // Needs to be 1.
            largeArc = 1;

            // Change sweep to change orientation of loop. 
            //sweep = 0;

            // Make drx and dry different to get an ellipse
            // instead of a circle.
            drx = 15;
            dry =...