D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
steveharoz
Full window
Github gist
animacy
<!DOCTYPE html> <meta charset="utf-8"> <style> body { background-color: black; color: white; font-family: sans-serif; } span, div { margin: 1em; float: left; } input { vertical-align: bottom; } svg { float: left; border: white 3px solid; border-radius: 4px; cursor: none; margin-top: 1em; } #cursor { fill: #293; } </style> <body> <div> <span>Show where they look: <input type="checkbox" id="showLook" checked></span> <br> <span>Perpendicular offset: <input type="range" id="offsetSlider" value="50" min="0" max="100"></span> <br> <span>Absolute offset: <input type="range" id="absoluteOffsetSlider" value="0" min="0" max="100"></span> <br> <span>Look perpendicular: <input type="checkbox" id="lookPerpendicular"></span> <br> </div> <svg></svg> <script src="https://d3js.org/d3.v4.min.js"></script> <script> var margin = 15; var width = 600 - margin*2, height = 500 - margin*2; var dartSpeed = 2; var perpendicularOffset = 50; var angleOffset = 0; var mouseLocation = [0,0]; class Dart { constructor(index) { this.x = Math.random() * width; this.y = Math.random() * height; this.velocityAngle = Math.random() * 360; this.velocityX = dartSpeed * Math.cos(this.velocityAngle); this.velocityY = dartSpeed * Math.sin(this.velocityAngle); this.lookAngle = 0; // the angle where this dart is looking this.lookX = 0; // the position where this dart is looking this.lookY = 0; // the position where this dart is looking this.lookSign = index % 2 ? 1 : -1; // looking to the right or left } updateMove() { this.x += this.velocityX; this.y += this.velocityY; if (this.x < 0 || this.x > width) { this.velocityX *= -1; } if (this.x < 0) { this.x *= -1; } if (this.x > width) { this.x = 2*width - this.x; } if (this.y < 0 || this.y > height) { this.velocityY *= -1; } if (this.y < 0) { this.y *= -1; } if (this.y > height) { this.y = 2*height - this.y; } this.lookAtMe(); } lookAtMe() { var absoluteOffset = +d3.select('#absoluteOffsetSlider').property('value'); var angle = Math.atan2(mouseLocation[1]-absoluteOffset-this.y, mouseLocation[0]-absoluteOffset-this.x); var perpendicular = angle - Math.PI/2 * this.lookSign; this.lookX = mouseLocation[0] - absoluteOffset + perpendicularOffset * Math.cos(perpendicular); this.lookY = mouseLocation[1] - absoluteOffset + perpendicularOffset * Math.sin(perpendicular); this.lookAngle = Math.atan2(this.lookY-this.y, this.lookX-this.x) * 180/Math.PI + angleOffset; } } var darts = d3.range(12).map(i => new Dart(i)); var svg = d3.select("body").select("svg") .attr("width", width + margin*2) .attr("height", height + margin*2) .append("g") .attr("transform", 'translate(' + [margin, margin] + ')' ) .attr("width", width) .attr("height", height); var dartGlyphs = svg.selectAll('path') .data(darts) .enter() .append('path') .attr("d", " M 10 0 L -10 -10 L -5 0 L -10 10") // arrow shape .attr("fill", (d,i) => d3.schemeCategory20[i % 20]) .attr("transform", d => 'translate(' + [d.x, d.y] + ')'); var cursor = svg.append('circle') .attr('id', 'cursor') .attr("r", 13); var lookAtGlyphs = svg.selectAll('.lookAt') .data(darts) .enter() .append('circle') .attr('class', 'lookAt') .attr("r", 3) .attr("fill", (d,i) => d3.schemeCategory20[i % 20]) .attr("transform", d => 'translate(' + [d.lookX, d.lookY] + ')'); var lookAtMean = svg.append('path').attr('class', 'lookAtMean') .attr("fill", 'white') .attr("d", d3.symbol().size(10).type(d3.symbolStar)()); d3.select(window).on("mousemove", () => { mouseLocation = d3.mouse(svg.node()); }); d3.timer(function() { // update settings angleOffset = d3.select('#lookPerpendicular').property('checked') ? 90 : 0; perpendicularOffset = +d3.select('#offsetSlider').property('value'); // update darts for(i=0; i < darts.length; i++) darts[i].updateMove(); // update glyphs cursor.attr("transform", 'translate(' + mouseLocation + ')'); dartGlyphs .attr("fill", (d,i) => d3.select('#showLook').property('checked') ? d3.schemeCategory20[i % 20] : 'white' ) .attr("transform", d => 'translate(' + [d.x, d.y] + ')' + 'rotate(' + d.lookAngle + ')'); lookAtGlyphs .attr("opacity", +d3.select('#showLook').property('checked')) .attr("transform", d => 'translate(' + [d.lookX, d.lookY] + ')'); lookAtMean .attr("opacity", +d3.select('#showLook').property('checked')) .attr("transform", 'translate(' + [ darts.map(d => d.lookX).reduce((a, b) => a + b) / darts.length, darts.map(d => d.lookY).reduce((a, b) => a + b) / darts.length] + ')'); }); </script>
Modified
http://d3js.org/d3.v4.min.js
to a secure url
https://d3js.org/d3.v4.min.js