console.clear() var sel = d3.select('body').html('') var c = d3.conventions({sel, layers: 'csd', margin: {left: 30, bottom: 40}}) var xMax = Math.floor(c.width/2) c.x.domain([0, xMax]) c.y.domain([0, 100]) d3.drawAxis(c) var [ctx, svg, div] = c.layers svg.select('.y').append('text') .text('ms per frame') .at({textAnchor: 'start', x: -25, y: 15, fill: '#000'}) var points = d3.range(150) .map(d => [Math.random()*c.width, Math.random()*c.height]) points.forEach(d => {d.vx = 0, d.vy = 0}) var r = 6 var svgCircles = svg.appendMany('circle', points) .translate(d => d) .at({r, fill: '#0ff', stroke: '#0ff', fillOpacity: .2}) var divCircles = div.appendMany('div', points) .translate(d => d) .st({ position: 'absolute', width: r*2, height: r*2, left: -r, top: -r, borderRadius: r*2 + 'px', background: 'rgba(255, 0, 255, .2)', backgroundOpacity: .2, border: '1px solid #f0f' }) var i = 0 var prevT = 0 if (window.timer) timer.stop() timer = d3.timer(t => { i++ var dt = t - prevT prevT = t var color = ['#0ff', '#f0f', '#ff0'][i % 3] var x = c.x(i) var y = c.y(dt) if (i > xMax){ i = i - xMax c.sel.selectAll('.time-bar').remove() } points.forEach(d => { d.vx = d3.clamp(-3, d.vx + Math.random()*.6 - .6*.5, 3) d.vy = d3.clamp(-3, d.vy + Math.random()*.6 - .6*.5, 3) d[0] += d.vx d[1] += d.vy if (d[0] < 0 || d[0] > c.width) d.vx = -d.vx if (d[1] < 0 || d[1] > c.height) d.vy = -d.vy }) if (i % 3 == 0){ svgCircles.translate(d => d) svg.append('path.time-bar') .at({d: `M ${x} ${c.height} V ${y}`, stroke: color}) } else if (i % 3 == 1){ divCircles.translate(d => d) div.append('div.time-bar') .st({left: x, top: y, height: c.height - y}) .st({width: 1, background: color, position: 'absolute'}) } else if (i % 3 == 2){ ctx.fillStyle = 'rgba(0, 0, 0, 0.2)' ctx.fillRect(-c.margin.left, -c.margin.top, c.totalWidth, c.totalHeight) ctx.beginPath() ctx.fillStyle = 'rgba(255, 255, 0, .2)' ctx.strokeStyle = '#ff0' points.forEach(([x, y]) => { ctx.moveTo(x + r, y) ctx.arc(x, y, r, 0, 2 * Math.PI) }) ctx.stroke() ctx.fill() ctx.strokeStyle = color ctx.beginPath() ctx.moveTo(x, y) ctx.lineTo(x, c.height) ctx.stroke() } })