block by veltman 259819801c0ff504d59ace06a9a6faec

Rainbow spinner #2

Full Screen

A canvas version of this rainbow spinner.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

var width = 960,
    height = 500;

var context = d3.select("body").append("canvas")
  .attr("width", width)
  .attr("height", height)
  .node()
  .getContext("2d");

var arc = d3.arc()
  .context(context);

var angles = {
  start: 0,
  end: 5 / 8
};

context.translate(width / 2, height / 2);

stretch("start");

d3.timer(function(t){

  angles.offset = t / 5000;
  draw();

});

function draw() {

  context.clearRect(0, 0, width, height);

  arc.innerRadius(175)
    .outerRadius(210);

  d3.range(0, 181).forEach(function(deg){

    context.fillStyle = context.strokeStyle = d3.interpolateRainbow(deg / 180);

    var start = angles.offset + deg / 180,
        end = start + 1 / 180;

    arc.startAngle(start * Math.PI * 2)
      .endAngle(end * Math.PI * 2);

    context.beginPath();
    arc();
    context.fill();
    context.stroke();

  });

  // lazy clip
  context.fillStyle = context.strokeStyle = "#fff";
  context.beginPath();
  arc.startAngle((angles.offset + angles.end) * Math.PI * 2)
    .endAngle((angles.offset + angles.start + 1) * Math.PI * 2)
    .innerRadius(170)
    .outerRadius(215)();
  context.fill();
  context.stroke();

}

function stretch(type) {

  var interpolate = d3.interpolateNumber(angles[type], angles[type] + 9 / 16);

  d3.select("body").transition()
    .delay(500)
    .duration(1000)
    .tween("angle", function(){

      return function(t){
        angles[type] = interpolate(t);
      };

    })
    .on("end", function(){
      stretch(type === "start" ? "end" : "start");
    });

}

</script>