Skip to content

Instantly share code, notes, and snippets.

@veltman
Last active July 3, 2016 04:27
Show Gist options
  • Save veltman/c4c995ace1bf181945fb to your computer and use it in GitHub Desktop.
Save veltman/c4c995ace1bf181945fb to your computer and use it in GitHub Desktop.
Fermat's rainbow
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
background-color: #000;
}
</style>
<body>
<script src="//d3js.org/d3.v4.0.0-alpha.18.min.js"></script>
<script>
var width = 960,
height = 500,
cx = width / 2,
cy = height / 2,
duration = 60000,
timer;
var rainbow = d3.scaleRainbow();
var angle = d3.scaleLinear()
.domain([0,1])
.range([(Math.sqrt(5) - 1) / 2,0])
.clamp(true);
var canvas = d3.select("body").append("canvas")
.attr("width", width)
.attr("height", height);
var context = canvas.node().getContext("2d");
var seeds = d3.range(fibonacci(18).pop()).map(function(d){
return {
index: d,
color: rainbow((1 + Math.sin(2 * Math.PI * angle.range()[0] * d)) / 2)
};
});
draw(0);
transition();
function transition() {
if (timer) {
timer.stop();
}
d3.timeout(function(){
timer = d3.timer(draw);
},1000);
}
function draw(t){
context.clearRect(0,0,width,height);
t = d3.easeCubicInOut(t / duration);
var ϕ = angle(t);
seeds.forEach(function(seed){
var θ = 2 * Math.PI * ϕ * seed.index,
r = Math.sqrt(seed.index) * 6;
context.fillStyle = seed.color;
context.beginPath();
context.arc(cx + r * Math.cos(θ),cy - r * Math.sin(θ),2,0,Math.PI*2);
context.fill();
});
// Back to sunflower, switch directions
if (t >= 1) {
angle.range(angle.range().reverse());
transition();
}
}
function fibonacci(n) {
return d3.range(n).reduce(function(arr, x, i){
return arr.concat((i < 2) ? i : arr[i-1] + arr[i-2]);
}, []);
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment