var width = 500, height = 500, r = 450 var svg = d3.select('html') .append('svg') .attr({width: width, height: height}) .append('g') .translate([10, height - 10]) svg.append('rect') .attr({width: width, height: height, opacity: 0, y: -height}) svg.append('circle') .attr('r', r) .style({stroke: 'black', fill: 'none', 'stroke-width': 2}) var gridG = svg.append('g') var trailG = svg.append('g') var draws = 1, drawsToSave = 20, curY = -1 setS(20) setInterval(step, 50) function step(){ if (curY < 0) return var dif = Math.pow(curX*s, 2) + Math.pow(curY*s, 2) - r*r var incX = dif < 0 var curG = trailG.append('g').datum(draws) curG.append('rect') .style({stroke: '#F0F', fill: 'black', 'fill-opacity': .2, 'stroke-width': 2}) .translate([curX*s - s/2, -curY*s - s/2]) .attr({width: s, height: s}) .datum(draws) if (incX){ curG.append('path.trail') .attr('d', ['M', curX*s, -curY*s, 'h', s].join(' ')) .style('stroke', 'black') curX++ } else{ curG.append('path.trail') .attr('d', ['M', curX*s, -curY*s, 'v', s].join(' ')) .style('stroke', 'black') curY-- } } function setS(newS){ while (curY >= 0){ step() } s = newS curX = 0 curY = Math.floor(r/s) draws++ trailG.selectAll('g') .style('opacity', function(d){ return d/draws*.1 }) .filter(function(d){ return draws - d > drawsToSave }) .remove() var grid = d3.range(0, width + s, s).map(function(x){ return d3.range(0, -height -s, -s).map(function(y){ return P(x, y) }) }) gridG.selectAll('*').remove() gridG.dataAppend(_.flatten(grid), 'circle') .attr('r', 1) .translate(ƒ()) } d3.select('svg') .on('click', function(){ curX = 0 curY = Math.floor(r/s) trailG.selectAll('*').remove() }) .on('mousemove', function(){ var pos = d3.mouse(this) drawsToSave = pos[1]/height*30 setS(pos[0]/width*100 + 8) })