var ƒ = d3.f var width = innerWidth, height = innerHeight, r = 50, cols = Math.ceil(innerWidth/r) + 1, rows = Math.ceil(innerHeight/r) + 1 var circles = d3.range(cols*rows).map(function(i){ return { x: (i % cols)*r, y: (i / cols >> 0) * r } }) var canvas = d3.select('body').html('') .append('canvas') .at({width, height}) .on('mousemove', function(){ var pos = d3.mouse(this) minSize = d3.scaleLinear().domain([0, width]).range([.1, 2])(pos[0]) change = d3.scaleLinear().domain([0, height]).range([.1, 10])(pos[1]) }) .node() var ctx = canvas.getContext('2d') ctx.globalCompositeOperation = 'xor'; var minSize = Math.sqrt(2) var change = 5 if (window.timer) window.timer.stop() window.timer = d3.timer(function(t){ ctx.clearRect(0, 0, width, height) ctx.fillStyle = '#000' circles.forEach(function(d){ var dist = Math.sqrt(Math.pow(width/2 - d.x, 2) + Math.pow(height/2 - d.y, 2)) var k = Math.sin(t/1000 - dist/200)*change + 2.5 k = Math.max(Math.sqrt(2), k) ctx.beginPath() ctx.moveTo(d.x + r/k, d.y) ctx.arc(d.x, d.y, r/k, 0, 2 * Math.PI) ctx.fill() }) })