bigapple/render.html

120 lines
2.9 KiB
HTML

<!DOCTYPE html>
<meta charset="utf-8">
<canvas width="2000" height="2000"></canvas>
<script src="https://d3js.org/d3.v4.js"></script>
<script>
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
width = canvas.width,
height = canvas.height;
// TODO
// - hover text
// - distance on links
// - full file name on nodes
// - list of all disks on nodes
// - size nodes by number of matching disks
// Double-click on a node and sort it in relation to all of its links
d3.json("levenshtein.json", function(error, graph) {
if (error) throw error;
var nodes = graph.nodes;
console.log(graph.links);
var links = [];
graph.links.forEach(function(link) {
if (link.distance < 200 && link.distance > 0) {
links.push(link);
}
});
console.log(links);
var simulation = d3.forceSimulation(nodes)
.force("charge", d3.forceManyBody().strength(-500))
.force("link", d3.forceLink(links)
.strength(1)
// TODO: Also add source and target radius so circles don't overlap
.distance(function(d) {return d.distance;}))
.force("x", d3.forceX())
.force("y", d3.forceY())
.on("tick", ticked);
d3.select(canvas)
.call(d3.drag()
.container(canvas)
.subject(dragsubject)
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended)
);
function ticked() {
context.clearRect(0, 0, width, height);
context.save();
context.translate(width / 2, height / 2);
context.beginPath();
links.forEach(drawLink);
context.strokeStyle = "#aaa";
context.stroke();
nodes.forEach(drawNode);
context.strokeStyle = "#fff";
context.stroke();
context.restore();
}
function dragsubject() {
return simulation.find(d3.event.x - width / 2, d3.event.y - height / 2);
}
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 drawLink(d) {
context.moveTo(d.source.x, d.source.y);
context.lineTo(d.target.x, d.target.y);
}
function drawNode(d) {
context.beginPath();
context.moveTo(d.x, d.y); // was d.x+3 for some reason
var radius = (Math.log10(d.radius)+1)*5
context.arc(d.x, d.y, radius, 0, 2 * Math.PI);
context.strokeStyle = "#000000"
context.strokeText(d.sha1, d.x+radius+5, d.y);
context.fillStyle = '#' + d.sha1.substr(0,6).toUpperCase();
context.fill();
}
function mouseOver(d, i) {
d3.select(this).append("text")
.text( d.x)
.attr("x", x(d.x))
.attr("y", y(d.y));
}
function mouseOut(d) {
}
});
</script>