|
<!doctype html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<title>Force Layout Link Scaling</title> |
|
<link rel="stylesheet" href="force-layout-scaling.css"> |
|
<script src="http://d3js.org/d3.v3.min.js"></script> |
|
</head> |
|
<body> |
|
<div class="controls"> |
|
<label>Gravity: <input id="gravitySlider" type="range" min=0 max=2 step=0.1> <span id="gravityValue"></span></label> |
|
<label>Charge Scaling: <input id="chargeSlider" type="range" min=0 max=400 step=10> <span id="chargeValue"></span></label> |
|
<label>Node Scaling: <input id="nodeSlider" type="range" min=0 max=4 step=0.1> <span id="nodeValue"></span></label> |
|
|
|
</div> |
|
<script> |
|
var width = 800; |
|
var height = 400; |
|
var numPoints = 100; |
|
var initGravity = 0.2; |
|
var svg = d3.select("body").append("svg") |
|
.attr("width", width).attr("height", height) |
|
.attr("viewBox", "0 0 " + width + " " + height) |
|
.attr("preserveAspectRatio", "xMidYMid"); |
|
|
|
var force = d3.layout.force().size([width,height]); |
|
var nodes = []; |
|
|
|
for (var j=0;j<numPoints;j++){ |
|
nodes[j] = { |
|
name: "Node " + j |
|
}; |
|
} |
|
|
|
var links = []; |
|
|
|
for (j=0;j<numPoints;j++){ |
|
var src = Math.floor(Math.random() * numPoints); |
|
var tar = Math.floor(Math.random() * numPoints); |
|
if (tar === src) { |
|
if (src != 0) { |
|
tar = src - 1; |
|
} else { |
|
tar = 1; |
|
} |
|
} |
|
links[j] = { |
|
source: src, |
|
target: tar |
|
}; |
|
} |
|
|
|
force.links(links); |
|
|
|
var linkSelection = svg.selectAll("line").data(links); |
|
linkSelection.enter() |
|
.insert("line") |
|
.classed("link", true); |
|
|
|
force.nodes(nodes); |
|
|
|
var nodeSelection = svg.selectAll("circle.node").data(nodes); |
|
nodeSelection.enter() |
|
.append("circle") |
|
.attr("r", 5) |
|
.classed("node", true) |
|
.call(force.drag); |
|
|
|
force.gravity(initGravity); |
|
|
|
force.on("start", function(){ |
|
force.charge(function(node,i){ |
|
var chargeScale = d3.select("#chargeSlider").property("valueAsNumber"); |
|
return -1*(chargeScale * node.weight + 30); |
|
}); |
|
}); |
|
|
|
force.on("tick", function(e){ |
|
var nodeScaling = d3.select("#nodeSlider").property("valueAsNumber"); |
|
linkSelection.attr("x1", function(d){return d.source.x;}) |
|
.attr("y1", function(d){return d.source.y;}) |
|
.attr("x2", function(d){return d.target.x;}) |
|
.attr("y2", function(d){return d.target.y;}); |
|
|
|
nodeSelection.attr("cx", function(d){return d.x;}) |
|
.attr("cy", function(d) {return d.y}) |
|
.attr("r", function(d){return d.weight * nodeScaling + 2;}); |
|
}); |
|
|
|
d3.select("#gravitySlider").on("change", function(){ |
|
var val = this.value; |
|
d3.select("#gravityValue").text(val); |
|
force.gravity(val); |
|
force.resume(); |
|
}); |
|
d3.select("#chargeSlider").on("change", function(){ |
|
var val = this.value; |
|
d3.select("#chargeValue").text(val); |
|
force.start(); |
|
}); |
|
d3.select("#nodeSlider").on("change", function(){ |
|
var val = this.value; |
|
d3.select("#nodeValue").text(val); |
|
force.resume(); |
|
}); |
|
|
|
|
|
// Main |
|
d3.select("#gravitySlider").property("value",force.gravity()); |
|
d3.select("#gravityValue").text(force.gravity()); |
|
d3.select("#chargeSlider").property("value", 0); |
|
d3.select("#chargeValue").text(0); |
|
d3.select("#nodeSlider").property("value", 0); |
|
d3.select("#nodeValue").text(0); |
|
force.start(); |
|
|
|
</script> |
|
</body> |
|
</html> |