Skip to content

Instantly share code, notes, and snippets.

@Develer
Last active June 1, 2016 12:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Develer/a95ba04783e2983634d8ec1a8abd2bc3 to your computer and use it in GitHub Desktop.
Save Develer/a95ba04783e2983634d8ec1a8abd2bc3 to your computer and use it in GitHub Desktop.
Force Dragging Curved Links d3.v4
license: gpl-3.0
height: 600
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.links path {
stroke: #aaa;
fill: none;
}
.nodes circle {
pointer-events: all;
stroke: none;
stroke-width: 40px;
}
</style>
<svg width="960" height="600"></svg>
<script src="https://d3js.org/d3.v4.0.0-alpha.40.min.js"></script>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var simulation = d3.forceSimulation()
.force("link", d3.forceLink())
.force("charge", d3.forceManyBody().distanceMax(100))
.force("center", d3.forceCenter(width / 2, height / 2));
d3.json("miserables.json", function(error, graph) {
if (error) throw error;
var nodes = graph.nodes.slice(),
links = [],
bilinks = [];
graph.links.forEach(function(link) {
var s = nodes[link.source],
t = nodes[link.target],
i = {}; // intermediate node
nodes.push(i);
links.push({source: s, target: i}, {source: i, target: t});
bilinks.push([s, i, t]);
});
simulation
.nodes(nodes)
.on("tick", ticked);
simulation
.force("link")
.links(links);
var link = svg.append("g").attr("class", "links")
.selectAll(".link")
.data(bilinks)
.enter().append("path");
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(graph.nodes)
.enter().append("circle")
.attr("r", 2.5)
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
function ticked() {
link.attr("d", function(d) {
return "M" + d[0].x + "," + d[0].y
+ "S" + d[1].x + "," + d[1].y
+ " " + d[2].x + "," + d[2].y;
});
node
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
});
function dragstarted(d) {
if (!d3.event.active) {
simulation.alphaTarget(0.3).restart()
}
simulation.fix(d);
}
function dragged(d) {
simulation.fix(d, d3.event.x, d3.event.y);
}
function dragended(d) {
if (!d3.event.active) {
simulation.alphaTarget(0);
}
simulation.unfix(d);
}
</script>
{
"nodes":[
{"name":"Myriel"},
{"name":"Napoleon"},
{"name":"Mlle.Baptistine"},
{"name":"Mme.Magloire"},
{"name":"CountessdeLo"},
{"name":"Geborand"},
{"name":"Champtercier"},
{"name":"Cravatte"},
{"name":"Count"},
{"name":"OldMan"},
{"name":"Labarre"},
{"name":"Valjean"},
{"name":"Marguerite"},
{"name":"Mme.deR"},
{"name":"Isabeau"},
{"name":"Gervais"},
{"name":"Tholomyes"},
{"name":"Listolier"},
{"name":"Fameuil"},
{"name":"Blacheville"},
{"name":"Favourite"},
{"name":"Dahlia"},
{"name":"Zephine"},
{"name":"Fantine"},
{"name":"Mme.Thenardier"},
{"name":"Thenardier"},
{"name":"Cosette"},
{"name":"Javert"},
{"name":"Fauchelevent"},
{"name":"Bamatabois"},
{"name":"Perpetue"},
{"name":"Simplice"},
{"name":"Scaufflaire"},
{"name":"Woman1"},
{"name":"Judge"},
{"name":"Champmathieu"},
{"name":"Brevet"},
{"name":"Chenildieu"},
{"name":"Cochepaille"},
{"name":"Pontmercy"},
{"name":"Boulatruelle"},
{"name":"Eponine"},
{"name":"Anzelma"},
{"name":"Woman2"},
{"name":"MotherInnocent"},
{"name":"Gribier"},
{"name":"Jondrette"},
{"name":"Mme.Burgon"},
{"name":"Gavroche"},
{"name":"Gillenormand"},
{"name":"Magnon"},
{"name":"Mlle.Gillenormand"},
{"name":"Mme.Pontmercy"},
{"name":"Mlle.Vaubois"},
{"name":"Lt.Gillenormand"},
{"name":"Marius"},
{"name":"BaronessT"},
{"name":"Mabeuf"},
{"name":"Enjolras"},
{"name":"Combeferre"},
{"name":"Prouvaire"},
{"name":"Feuilly"},
{"name":"Courfeyrac"},
{"name":"Bahorel"},
{"name":"Bossuet"},
{"name":"Joly"},
{"name":"Grantaire"},
{"name":"MotherPlutarch"},
{"name":"Gueulemer"},
{"name":"Babet"},
{"name":"Claquesous"},
{"name":"Montparnasse"},
{"name":"Toussaint"},
{"name":"Child1"},
{"name":"Child2"},
{"name":"Brujon"},
{"name":"Mme.Hucheloup"}
],
"links":[
{"source":1,"target":0},
{"source":2,"target":0},
{"source":3,"target":0},
{"source":3,"target":2},
{"source":4,"target":0},
{"source":5,"target":0},
{"source":6,"target":0},
{"source":7,"target":0},
{"source":8,"target":0},
{"source":9,"target":0},
{"source":11,"target":10},
{"source":11,"target":3},
{"source":11,"target":2},
{"source":11,"target":0},
{"source":12,"target":11},
{"source":13,"target":11},
{"source":14,"target":11},
{"source":15,"target":11},
{"source":17,"target":16},
{"source":18,"target":16},
{"source":18,"target":17},
{"source":19,"target":16},
{"source":19,"target":17},
{"source":19,"target":18},
{"source":20,"target":16},
{"source":20,"target":17},
{"source":20,"target":18},
{"source":20,"target":19},
{"source":21,"target":16},
{"source":21,"target":17},
{"source":21,"target":18},
{"source":21,"target":19},
{"source":21,"target":20},
{"source":22,"target":16},
{"source":22,"target":17},
{"source":22,"target":18},
{"source":22,"target":19},
{"source":22,"target":20},
{"source":22,"target":21},
{"source":23,"target":16},
{"source":23,"target":17},
{"source":23,"target":18},
{"source":23,"target":19},
{"source":23,"target":20},
{"source":23,"target":21},
{"source":23,"target":22},
{"source":23,"target":12},
{"source":23,"target":11},
{"source":24,"target":23},
{"source":24,"target":11},
{"source":25,"target":24},
{"source":25,"target":23},
{"source":25,"target":11},
{"source":26,"target":24},
{"source":26,"target":11},
{"source":26,"target":16},
{"source":26,"target":25},
{"source":27,"target":11},
{"source":27,"target":23},
{"source":27,"target":25},
{"source":27,"target":24},
{"source":27,"target":26},
{"source":28,"target":11},
{"source":28,"target":27},
{"source":29,"target":23},
{"source":29,"target":27},
{"source":29,"target":11},
{"source":30,"target":23},
{"source":31,"target":30},
{"source":31,"target":11},
{"source":31,"target":23},
{"source":31,"target":27},
{"source":32,"target":11},
{"source":33,"target":11},
{"source":33,"target":27},
{"source":34,"target":11},
{"source":34,"target":29},
{"source":35,"target":11},
{"source":35,"target":34},
{"source":35,"target":29},
{"source":36,"target":34},
{"source":36,"target":35},
{"source":36,"target":11},
{"source":36,"target":29},
{"source":37,"target":34},
{"source":37,"target":35},
{"source":37,"target":36},
{"source":37,"target":11},
{"source":37,"target":29},
{"source":38,"target":34},
{"source":38,"target":35},
{"source":38,"target":36},
{"source":38,"target":37},
{"source":38,"target":11},
{"source":38,"target":29},
{"source":39,"target":25},
{"source":40,"target":25},
{"source":41,"target":24},
{"source":41,"target":25},
{"source":42,"target":41},
{"source":42,"target":25},
{"source":42,"target":24},
{"source":43,"target":11},
{"source":43,"target":26},
{"source":43,"target":27},
{"source":44,"target":28},
{"source":44,"target":11},
{"source":45,"target":28},
{"source":47,"target":46},
{"source":48,"target":47},
{"source":48,"target":25},
{"source":48,"target":27},
{"source":48,"target":11},
{"source":49,"target":26},
{"source":49,"target":11},
{"source":50,"target":49},
{"source":50,"target":24},
{"source":51,"target":49},
{"source":51,"target":26},
{"source":51,"target":11},
{"source":52,"target":51},
{"source":52,"target":39},
{"source":53,"target":51},
{"source":54,"target":51},
{"source":54,"target":49},
{"source":54,"target":26},
{"source":55,"target":51},
{"source":55,"target":49},
{"source":55,"target":39},
{"source":55,"target":54},
{"source":55,"target":26},
{"source":55,"target":11},
{"source":55,"target":16},
{"source":55,"target":25},
{"source":55,"target":41},
{"source":55,"target":48},
{"source":56,"target":49},
{"source":56,"target":55},
{"source":57,"target":55},
{"source":57,"target":41},
{"source":57,"target":48},
{"source":58,"target":55},
{"source":58,"target":48},
{"source":58,"target":27},
{"source":58,"target":57},
{"source":58,"target":11},
{"source":59,"target":58},
{"source":59,"target":55},
{"source":59,"target":48},
{"source":59,"target":57},
{"source":60,"target":48},
{"source":60,"target":58},
{"source":60,"target":59},
{"source":61,"target":48},
{"source":61,"target":58},
{"source":61,"target":60},
{"source":61,"target":59},
{"source":61,"target":57},
{"source":61,"target":55},
{"source":62,"target":55},
{"source":62,"target":58},
{"source":62,"target":59},
{"source":62,"target":48},
{"source":62,"target":57},
{"source":62,"target":41},
{"source":62,"target":61},
{"source":62,"target":60},
{"source":63,"target":59},
{"source":63,"target":48},
{"source":63,"target":62},
{"source":63,"target":57},
{"source":63,"target":58},
{"source":63,"target":61},
{"source":63,"target":60},
{"source":63,"target":55},
{"source":64,"target":55},
{"source":64,"target":62},
{"source":64,"target":48},
{"source":64,"target":63},
{"source":64,"target":58},
{"source":64,"target":61},
{"source":64,"target":60},
{"source":64,"target":59},
{"source":64,"target":57},
{"source":64,"target":11},
{"source":65,"target":63},
{"source":65,"target":64},
{"source":65,"target":48},
{"source":65,"target":62},
{"source":65,"target":58},
{"source":65,"target":61},
{"source":65,"target":60},
{"source":65,"target":59},
{"source":65,"target":57},
{"source":65,"target":55},
{"source":66,"target":64},
{"source":66,"target":58},
{"source":66,"target":59},
{"source":66,"target":62},
{"source":66,"target":65},
{"source":66,"target":48},
{"source":66,"target":63},
{"source":66,"target":61},
{"source":66,"target":60},
{"source":67,"target":57},
{"source":68,"target":25},
{"source":68,"target":11},
{"source":68,"target":24},
{"source":68,"target":27},
{"source":68,"target":48},
{"source":68,"target":41},
{"source":69,"target":25},
{"source":69,"target":68},
{"source":69,"target":11},
{"source":69,"target":24},
{"source":69,"target":27},
{"source":69,"target":48},
{"source":69,"target":41},
{"source":70,"target":25},
{"source":70,"target":69},
{"source":70,"target":68},
{"source":70,"target":11},
{"source":70,"target":24},
{"source":70,"target":27},
{"source":70,"target":41},
{"source":70,"target":58},
{"source":71,"target":27},
{"source":71,"target":69},
{"source":71,"target":68},
{"source":71,"target":70},
{"source":71,"target":11},
{"source":71,"target":48},
{"source":71,"target":41},
{"source":71,"target":25},
{"source":72,"target":26},
{"source":72,"target":27},
{"source":72,"target":11},
{"source":73,"target":48},
{"source":74,"target":48},
{"source":74,"target":73},
{"source":75,"target":69},
{"source":75,"target":68},
{"source":75,"target":25},
{"source":75,"target":48},
{"source":75,"target":41},
{"source":75,"target":70},
{"source":75,"target":71},
{"source":76,"target":64},
{"source":76,"target":65},
{"source":76,"target":66},
{"source":76,"target":63},
{"source":76,"target":62},
{"source":76,"target":48},
{"source":76,"target":58}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment