var width = innerWidth, height = innerHeight, overlap = 10, numPoly = 25 var canvas = d3.select('body').append('canvas') .attr('width', width) .attr('height', height) var ctx = canvas.node().getContext('2d') var curColor = '#000' drawPolygons('#000') function drawPolygons(color){ var vertices = d3.range(numPoly).map(function(d) { return [Math.random()*width, Math.random()*height] }) var voronoi = d3.geom.voronoi().clipExtent([[0, 0], [width, height]]) var polygons = voronoi(vertices) var q = queue(overlap) _.sortBy(polygons, function(d){ return d3.min(d, ƒ(0)) }) .forEach(function(d, i){ q.defer(drawSpiral, d, i, color) }) q.awaitAll(function(){ drawPolygons(color == '#000' ? '#fff' : '#000') }) } function drawSpiral(polygon, i, color, cb){ var duration = 0 var points = polygon.slice() var count = 0 setTimeout(drawNext, i < overlap ? i*100 : 0) function drawNext(){ var curPoint = points.shift() var nextPoint = points[0] if (curColor != color) ctx.strokeStyle = curColor = color ctx.beginPath() ctx.lineTo(curPoint[0], curPoint[1]) ctx.lineTo(nextPoint[0], nextPoint[1]) ctx.stroke() var percent = 4/dist(curPoint, nextPoint) var x = curPoint[0]*(1 - percent) + nextPoint[0]*percent var y = curPoint[1]*(1 - percent) + nextPoint[1]*percent if (dist([x, y], nextPoint) > 1) points.push([x, y]) points.length > 2 && count++ < 500 ? setTimeout(drawNext, duration) : cb() } } function dist(a, b){ return Math.sqrt( Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2)) }