|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<style> |
|
</style> |
|
<canvas></canvas> |
|
<script src="https://d3js.org/d3.v4.min.js"></script> |
|
<script> |
|
var width = 960, |
|
height = 600; |
|
|
|
var linkColor = d3.scaleThreshold() |
|
.domain(d3.range(0,200, 20)) |
|
.range(d3.range(0.5,1.0,0.05)); |
|
|
|
var canvas = d3.select("canvas") |
|
.attr("width", width) |
|
.attr("height", height); |
|
|
|
var context = canvas.node().getContext("2d"); |
|
|
|
var simulation = d3.forceSimulation() |
|
.force("link", d3.forceLink().id(function(d) { return d.id; }).distance(22).strength(0.2)) |
|
.force("charge", d3.forceManyBody().strength(-6).distanceMax(380)) |
|
.force("center", d3.forceCenter(width / 2, height / 2)); |
|
|
|
var graph = {}; |
|
|
|
d3.text("lock1074.mtx", function(error, raw) { |
|
if (error) throw error; |
|
|
|
var node_set = d3.set(); |
|
|
|
var pairs = raw.split("\n") |
|
.slice(14) |
|
.map(function(d) { return d.split(" "); }); |
|
|
|
pairs.forEach(function(d) { |
|
node_set.add(d[0]); |
|
node_set.add(d[1]); |
|
}); |
|
|
|
graph.nodes = node_set.values().map(function(d) { |
|
return { |
|
id: d |
|
}; |
|
}); |
|
|
|
graph.links = pairs.map(function(d) { |
|
return { |
|
source: d[0], |
|
target: d[1] |
|
} |
|
}) |
|
.filter(function(d) { |
|
return d.source !== d.target; |
|
}); |
|
|
|
simulation |
|
.nodes(graph.nodes) |
|
|
|
simulation.force("link") |
|
.links(graph.links); |
|
|
|
d3.range(10).forEach(simulation.tick); |
|
|
|
simulation |
|
.on("tick", ticked); |
|
|
|
canvas.call(d3.drag() |
|
.container(canvas.node()) |
|
.subject(dragsubject) |
|
.on("start", dragstarted) |
|
.on("drag", dragged) |
|
.on("end", dragended)); |
|
|
|
function ticked() { |
|
context.clearRect(0, 0, width, height); |
|
|
|
context.globalAlpha = 0.2; |
|
drawLinks(graph.links); |
|
|
|
context.globalAlpha = 1; |
|
context.fillStyle = d3.interpolateViridis(0.15); |
|
graph.nodes.forEach(drawNode); |
|
} |
|
|
|
function dragsubject() { |
|
return simulation.find(d3.event.x, d3.event.y); |
|
} |
|
}); |
|
|
|
function dragstarted() { |
|
if (!d3.event.active) simulation.alphaTarget(0.3).restart(); |
|
d3.event.subject.fx = d3.event.subject.x; |
|
d3.event.subject.fy = d3.event.subject.y; |
|
} |
|
|
|
function dragged() { |
|
d3.event.subject.fx = d3.event.x; |
|
d3.event.subject.fy = d3.event.y; |
|
} |
|
|
|
function dragended() { |
|
if (!d3.event.active) simulation.alphaTarget(0); |
|
d3.event.subject.fx = null; |
|
d3.event.subject.fy = null; |
|
} |
|
|
|
function drawLinks(links) { |
|
var linkBatches = d3.map(); |
|
linkColor.range().map(function(d, i) { linkBatches.set(d, []);}); |
|
links.forEach(function(d) { |
|
var distance = Math.sqrt( Math.pow(d.source.x - d.target.x, 2) + Math.pow(d.source.y - d.target.y, 2)); |
|
var batch = linkColor(distance); |
|
var currentList = linkBatches.get(batch); |
|
currentList.push([[d.source.x, d.source.y],[d.target.x, d.target.y]]); |
|
linkBatches.set(batch, currentList); |
|
}); |
|
|
|
linkBatches.each(function(v, k) { |
|
context.beginPath(); |
|
v.forEach(function(points) { |
|
context.moveTo(points[0][0], points[0][1]); |
|
context.lineTo(points[1][0], points[1][1]); |
|
}); |
|
context.strokeStyle = d3.interpolatePlasma(parseFloat(k)); |
|
context.stroke(); |
|
}); |
|
} |
|
|
|
function drawNode(d) { |
|
// context.fillStyle = d3.interpolateMagma(Math.sqrt(d.vx*d.vx + d.vy*d.vy)); |
|
context.fillRect(d.x-0.75, d.y-0.75, 1.5, 1.5); |
|
} |
|
|
|
</script> |