Skip to content

Instantly share code, notes, and snippets.

@larsenmtl
Last active January 13, 2016 18:10
Show Gist options
  • Save larsenmtl/ceeb3162fefe05bd454e to your computer and use it in GitHub Desktop.
Save larsenmtl/ceeb3162fefe05bd454e to your computer and use it in GitHub Desktop.
Letter Spitter

Press any letter on the keyboard.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
text {
fill: steelblue;
font-size: 30px;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var width = window.innerWidth - 40,
height = (window.innerHeight * 1.75) - 40,
padding = 6, // separation between nodes
radius = 15;
var m = 11 // total number of coloumns;
d3.select('body')
.style('height', height + 'px')
.style('overflow-y', 'hidden');
var x = d3.scale.ordinal()
.domain(d3.range(m))
.rangePoints([0, width], 1);
function makeNode(letter){
var column = 0;
switch(letter) {
case 'Q':
case 'A':
column = 0;
break;
case 'W':
case 'Z':
column = 1;
break;
case 'S':
case 'X':
column = 2;
break;
case 'E':
case 'D':
column = 3;
break;
case 'C':
case 'R':
case 'T':
case 'F':
case 'V':
column = 4;
break;
case 'Y':
case 'H':
case 'G':
case 'B':
column = 5;
break;
case 'U':
case 'N':
column = 6;
break;
case 'J':
case 'M':
column = 7;
break;
case 'I':
case 'K':
column = 8;
break;
case 'O':
case 'L':
column = 9;
break;
case 'P':
column = 10;
break;
default:
return false;
};
return {
letter: letter,
x: width/2,
y: 0,
cx: x(column),
cy: height / 2,
radius: 10
};
}
var nodes = [];
var force = d3.layout.force()
.nodes(nodes)
.size([width, height])
.gravity(0)
.charge(0)
.on("tick", tick);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
function update(letter){
var node = makeNode(letter);
if (node){
nodes.push(node);
letters = svg.selectAll("text")
.data(nodes);
letters
.enter()
.append("text")
.text(function(d){
return d.letter;
});
force.nodes(nodes);
force.start();
}
}
d3.select("body")
.on("keydown", function() {
update(String.fromCharCode(d3.event.keyCode));
});
function tick(e) {
letters
.each(gravity(.2 * e.alpha))
.each(collide(.5))
.attr("x", function(d) { return d.x; })
.attr("y", function(d) { return d.y; });
letters.attr("x", function(d) { return d.x = Math.max(radius, Math.min(width - radius, d.x)); })
.attr("y", function(d) { return d.y = Math.max(radius, Math.min((height / 2) - radius, d.y)); });
}
// Move nodes toward cluster focus.
function gravity(alpha) {
return function(d) {
d.y += (d.cy - d.y) * alpha;
d.x += (d.cx - d.x) * alpha;
};
}
// Resolve collisions between nodes.
function collide(alpha) {
var quadtree = d3.geom.quadtree(nodes);
return function(d) {
var r = (2 * radius) + padding,
nx1 = d.x - r,
nx2 = d.x + r,
ny1 = d.y - r,
ny2 = d.y + r;
quadtree.visit(function(quad, x1, y1, x2, y2) {
if (quad.point && (quad.point !== d)) {
var x = d.x - quad.point.x,
y = d.y - quad.point.y,
l = Math.sqrt(x * x + y * y),
r = (2 * radius);
if (l < r) {
l = (l - r) / l * alpha;
d.x -= x *= l;
d.y -= y *= l;
quad.point.x += x;
quad.point.y += y;
}
}
return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
});
};
}
document.addEventListener("DOMContentLoaded", function(event) {
self.frameElement.focus();
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment