More fun with words.
Text rasterization from Andrew Mollica. Idea of drawing links between points on a random walk from Mike Bostock.
More fun with words.
Text rasterization from Andrew Mollica. Idea of drawing links between points on a random walk from Mike Bostock.
<!DOCTYPE html> | |
<meta charset='utf-8'> | |
<body style='background: #fff;'> | |
<canvas width='960' height='300'></canvas> | |
</body> | |
<script src='//d3js.org/d3.v4.min.js'></script> | |
<script> | |
var width = 960, | |
height = 300, | |
s = 2, | |
w = Math.floor(960/s), | |
h = Math.floor(300/s) | |
var points = d3.range(w*h).map(function(i){ | |
return {x: i % w, y: i/w >> 0, i: i} | |
}) | |
points.forEach(function(d, i){ | |
d.px = d.x*s | |
d.py = d.y*s | |
d.l = d.x ? points[i - 1] : d | |
d.t = d.y ? points[i - w] : d | |
}) | |
var canvas = d3.select('canvas').node() | |
var ctx = canvas.getContext('2d') | |
setPointsOn(points) | |
var mPos = {px: 0, py: 0} | |
d3.select('body') | |
.on('mousemove', function(){ | |
mPos = {px: d3.mouse(this)[0], py: d3.mouse(this)[1]} }) | |
.on('click', function(){ | |
if (Math.random() < .5){ | |
onPoints.forEach(function(d){ d.y = h - d.y }) | |
} else{ | |
onPoints.forEach(function(d){ d.x = w - d.x }) | |
} | |
}) | |
var onPoints = points.filter(function(d){ return d.on }) | |
d3.timer(function(t){ | |
ctx.clearRect(0, 0, width, height); | |
ctx.fillStyle = '#000' | |
ctx.fillRect(0, 0, width, height); | |
ctx.beginPath() | |
onPoints.forEach(function(d, i){ | |
var dx = (Math.random() - .5)*1 | |
var dy = (Math.random() - .5)*1 | |
if (isWithin(d, mPos, 50)){ | |
dx += mPos.px - d.px | |
dy += mPos.py - d.py | |
dx *= -1/5 | |
dy *= -1/5 | |
if (Math.random() < .4){ | |
d.px = d.x*s | |
d.py = d.y*s | |
dx = 0 | |
dy = 0 | |
} | |
} | |
else if (Math.random() < .3){ | |
dx = xor(dx < 0, d.x*s - d.px < 0) ? -dx : dx | |
dy = xor(dy < 0, d.y*s - d.py < 0) ? -dy : dy | |
dx /= 1/5 | |
dy /= 1/5 | |
// d.px = d.x*s | |
// d.py = d.y*s | |
// dx = 0 | |
// dy = 0 | |
} | |
d.px += dx | |
d.py += dy | |
if (d.l.on && isWithin(d, d.l, 50)){ | |
ctx.moveTo(d.px, d.py) | |
ctx.lineTo(d.l.px, d.l.py) | |
} | |
if (d.t.on && isWithin(d, d.t, 50)){ | |
ctx.moveTo(d.px, d.py) | |
ctx.lineTo(d.t.px, d.t.py) | |
} | |
}) | |
ctx.strokeStyle = 'rgba(0,255,0,.2)' | |
ctx.lineWidth = 1 | |
ctx.stroke() | |
}) | |
function setPointsOn(points) { | |
ctx.font = '600 300px sans-serif' | |
ctx.textAlign = 'center'; | |
ctx.textBaseline = 'middle'; | |
ctx.fillText('words', width/2, height/2); | |
var imageData = ctx.getImageData(0, 0, width, height).data | |
points.forEach(function(d){ | |
d.on = imageData[(d.py*width + d.px)*4 + 3] | |
}) | |
} | |
function xor(a, b){ return (a || b) && !(a && b) } | |
function isWithin(a, b, dist){ | |
return Math.abs(a.px - b.px) + Math.abs(a.py - b.py) < dist | |
} | |
d3.select(self.frameElement).style('height', h*s + 'px'); | |
</script> |