var sel = d3.select('body').html('') var {layers: [ctx], width, height} = d3.conventions({sel, layers: 'c'}) ctx.globalCompositeOperation = 'xor' var n = 3 var r = width/(n + 1)/4 var circles = [] d3.range(n).forEach(i => { d3.range(n).forEach(j => { circles.push({x: r*2 + r*i*2, y: r*2 + r*j*2, i: j + i*n + 1}) }) }) var pairs = d3.cross(circles, circles).filter(([a, b]) => a.i > b.i) var i = 0 if (window.timer) window.timer.stop() window.timer = d3.timer(function(t){ i++ ctx.clearRect(0, 0, width, height) ctx.beginPath() circles.forEach(d => { ctx.moveTo(d.x + r, d.y) ctx.arc(d.x, d.y, r, 0, 2*Math.PI) }) ctx.stroke() ctx.lineWidth = 3 pairs.forEach(([a, b]) => { ctx.beginPath() ctx.moveTo(a.x + Math.cos(t/1000+ a.i/2)*r, a.y + Math.sin(t/1000+ a.i/2)*r) ctx.lineTo(b.x + Math.cos(t/1000+ b.i/2)*r, b.y + Math.sin(t/1000+ b.i/2)*r) ctx.stroke() }) })