D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
syntagmatic
Full window
Github gist
Ulam Animated
<meta charset="utf-8"> <title>Ulam Spirals</title> <style> html, body { margin: 0; padding: 0; width: 100%; height: 100%; background: #000; color: #eee; font: 11px 'Lucida Grande', sans-serif; } a, a:visited { color: #62d7ff; text-decoration: none; } footer { color: #fff; position: absolute; bottom: 0; right: 15; text-align: center; font-size: 12px; padding: 4px; background: rgba(0,0,0,0.5); } </style> <body> <canvas id="canvas" width=960 height=500></canvas> <footer>Ulam Spirals, adapted from <a href="https://www.bigblueboo.com/prime/">Prime Explorer</a></footer> </body> <script src="dat.gui.js"></script> <script> window.requestAnimFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function( callback ){ window.setTimeout(callback, 1000 / 60); }; window.onload = function() { var canvas = document.getElementById("canvas"); var width = canvas.width = document.body.clientWidth, height = canvas.height = document.body.clientHeight, size = 4, speed = 1, ulamN = 4, max = 3e4, start = 1, numcols = Math.floor(width / size), numrows = Math.floor(height / size), colors = ["#ffc344", "#000000"]; var ctx = canvas.getContext("2d"); ctx.save(); var latest = 0; function plotUlam(n) { // rerender invalidation var current = ++latest; // reset canvas ctx.restore(); ctx.save(); ctx.fillStyle = colors[0]; ctx.clearRect(0,0,width,height); ctx.translate(width/2,height/2); var maxRunLength = 1; var runLength = 1; var runCount = n - 2; var integer = 0; function step() { integer++; // our work is complete if (integer > max) return false; // our work was interrupted if (latest > current) return false; // transform the geometry ctx.translate(size,0); runLength--; if (runLength < 1) { runCount--; if (runCount < 1) { runCount = n - 2; maxRunLength++; } runLength = maxRunLength; ctx.rotate(Math.PI * 2 / n); } // perform tests on the integer var prime = isPrime(integer + start - 1); // render primes differently if (!prime) return; ctx.fillStyle = integer == 1 ? "red" : colors[0]; ctx.globalAlpha = 4 / Math.log(integer); // render the integer ctx.fillRect(-size/2, -size/2, size, size); }; var ii = max; // number of integers to render at once while (ii-- > 0) { step(); } function nextPlot() { if (latest == current) { start += speed; field.start = start; plotUlam(n); } } requestAnimFrame(nextPlot); } /* Primality Testing */ // https://www.javascripter.net/faq/numberisprime.htm function leastFactor(n){ if (isNaN(n) || !isFinite(n)) return NaN; if (n==0) return 0; if (n%1 || n*n<2) return 1; if (n%2==0) return 2; if (n%3==0) return 3; if (n%5==0) return 5; var m = Math.sqrt(n); for (var i=7;i<=m;i+=30) { if (n%i==0) return i; if (n%(i+4)==0) return i+4; if (n%(i+6)==0) return i+6; if (n%(i+10)==0) return i+10; if (n%(i+12)==0) return i+12; if (n%(i+16)==0) return i+16; if (n%(i+22)==0) return i+22; if (n%(i+24)==0) return i+24; } return n; } function isPrime (n) { if (isNaN(n) || !isFinite(n) || n%1 || n<2) return false; if (n==leastFactor(n)) return true; return false; } /* Plot some primes */ plotUlam(ulamN); /* Interactive Parameters with Dat.Gui*/ var Gui = function() { this.ulam = ulamN; this.size = size; this.max = max; this.start = start; this.speed = speed; this.color1 = colors[0]; this.color2 = colors[1]; }; var field = new Gui(); var gui = new dat.GUI(); var ulam = gui.add(field, 'ulam', 3, 10).step(1); var sizer = gui.add(field, 'size', 0.5, 6).step(0.5); var maxer = gui.add(field, 'max', 500, 1.5e5).step(500); var starter = gui.add(field, 'start', 1, 1e5).step(1).listen(); var speeder = gui.add(field, 'speed', 0, 10).step(1).listen(); var color1 = gui.addColor(field, 'color1'); var color2 = gui.addColor(field, 'color2'); ulam.onChange(function(v) { ulamN = v; plotUlam(ulamN); }); sizer.onChange(function(v) { size = v; plotUlam(ulamN); }); maxer.onChange(function(v) { max = v; plotUlam(ulamN); }); starter.onChange(function(v) { start = v; plotUlam(ulamN); }); speeder.onChange(function(v) { speed = v; plotUlam(ulamN); }); color1.onChange(function(v) { colors[0] = v; plotUlam(ulamN); }); color2.onChange(function(v) { colors[1] = v; document.body.style.background = colors[1]; }); }; </script>