Multiple Links Between Two Nodes in D3.js Force Directed Layout

A simple way to handle if there are multiple links between to nodes in the force directed layout implemented in D3.js.

by Guill84

HTML

<script src="http://d3js.org/queue.v1.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="http://d3js.org/d3.v2.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
<div id="graphContainer" class="graphContainer">
</div>

CSS

path.link {
    fill: none;
    stroke: #c0c0c0;
    stroke-width: 2px;
}	

circle {
    fill: #ccc;
    stroke: #333;
    stroke-width: 1.5px;
}

text {
    font: 12px sans-serif;
    pointer-events: none;
}

text.shadow {
    stroke: #fff;
    stroke-width: 3px;
    stroke-opacity: .8;
}

body {
    background-image: url
    margin: 0px;
}

.graphContainer {
    text-shadow: -1px -1px 0 white, 1px -1px 0 white, -1px 1px 0 white, 1px 1px 0 white;
}

JavaScript

$(function(){
    var data = {
        "nodes": [
            { "id": 0, "name": "A", "x":200, "y":20, "fixed":"TRUE" },
            { "id": 1, "name": "B","x":500, "y":250, "fixed":"TRUE" },
            { "id": 2, "name": "C", "x":390, "y":320, "fixed":"TRUE" },
            { "id": 3, "name": "D", "x":400, "y":420, "fixed":"TRUE" }
        ],
        "links": [     
            { "source": 0, "target": 1, "name": "A->B" },
            { "source": 0, "target": 2, "name": "A->C" },
            { "source": 0, "target": 3, "name": "A->D" },
            
            { "source": 1, "target": 0, "name": "B->A" },
            { "source": 1, "target": 2, "name": "B->C" },
            { "source": 1, "target": 3, "name": "B->D" },
            
            { "source": 2, "target": 0, "name": "C->A" },
            { "source": 2, "target": 1, "name": "C->B" },
            { "source": 2, "target": 3, "name": "C->D" },
            
            { "source": 3, "target": 0, "name": "D->A" },
            { "source": 3, "target": 1, "name": "D->B" },
            { "source": 3, "target": 2, "name": "D->C" }
        ]
    };			
    
    // used to store the number of links between two nodes. 
    // mLinkNum[data.links[i].source + "," + data.links[i].target] = data.links[i].linkindex;
    var mLinkNum = {};
    
    // sort links first
    sortLinks();								
    
    // set up linkIndex and linkNumer, because it may possible multiple links share the same source and target node
    setLinkIndexAndNum();
    
    var w = 600,
        h = 500;
    
    var force = d3.layout.force()
                  .nodes(d3.values(data.nodes))
                  .links(data.links)
                  .size([w, h])
                  .linkDistance(150)
                  .charge(-300)
                  .on("tick", tick)
                  .start();
    
    var svg = d3.select(".graphContainer").append("svg:svg")
                .attr("width", w)
                .attr("height", h);
    
    var path =...