block by steveharoz 2da60f7a3bf44e10a35d99034172688c

Epicyclic Gearing

Full Screen

Time the span between frames.

12 frames with an animated SVG are shown via d3.timer(). The elapsed time of each frame is put in an array, which is logged to the console after 150 runs (~1.5 minutes).

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<style>

body {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  width: 960px;
  height: 500px;
  position: relative;
}

path {
  fill-rule: evenodd;
  stroke: #333;
  stroke-width: 2px;
  fill: #6baed6;
}

</style>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

var width = 960,
    height = 500,
    radius = 140;

var offset = 0,
    speed = .1,
    start = Date.now();

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")scale(.55)");

var frame = svg.append("g");

frame.append("g")
  .attr("transform", "translate(-200, -200)")
  .append("path")
    .attr("d", gear(16, radius, radius/7));
frame.append("g")
  .attr("transform", "translate(200, -200)")
  .append("path")
    .attr("d", gear(16, radius, radius/7));
frame.append("g")
  .attr("transform", "translate(-200, 200)")
  .append("path")
    .attr("d", gear(16, radius, radius/7));
frame.append("g")
  .attr("transform", "translate(200, 200)")
  .append("path")
    .attr("d", gear(16, radius, radius/7));

// get path for a gear
function gear(teethCount, radius, teethSize = 8) {
  var r2 = Math.abs(radius),
      r0 = r2 - teethSize,
      r1 = r2 + teethSize,
      da = Math.PI / teethCount,
      a0 = -Math.PI / 2,
      i = -1,
      path = ["M", r0 * Math.cos(a0), ",", r0 * Math.sin(a0)];
  while (++i < teethCount) path.push(
      "A", r0, ",", r0, " 0 0,1 ", r0 * Math.cos(a0 += da), ",", r0 * Math.sin(a0),
      "L", r2 * Math.cos(a0), ",", r2 * Math.sin(a0),
      "L", r1 * Math.cos(a0 += da / 3), ",", r1 * Math.sin(a0),
      "A", r1, ",", r1, " 0 0,1 ", r1 * Math.cos(a0 += da / 3), ",", r1 * Math.sin(a0),
      "L", r2 * Math.cos(a0 += da / 3), ",", r2 * Math.sin(a0),
      "L", r0 * Math.cos(a0), ",", r0 * Math.sin(a0));
  path.push(",Z");
  return path.join("");
}

var previous_elapsed = 0;
var frameTimes = new Array(12);
var frameIndex = 0;
var show = false;
var runCount = 0;
var outputString = "";

var mytimer = d3.timer(function(elapsed) {
  // skip every other frame
  // if (elapsed - previous_elapsed < 17)
  //   return;

  // animate
  var angle = (Date.now() - start) * speed,
      transform = function(d) { return "rotate(" + angle + ")"; };
  frame.selectAll("path").attr("transform", transform);

  // store frame duration
  frameTimes[frameIndex] = (elapsed - previous_elapsed).toFixed(2);
  frameIndex++;
  previous_elapsed = elapsed;
  // log to console after some number of frames
  if (frameIndex >= frameTimes.length) {
    if (show)
      outputString += frameTimes.join() + "\n";
    runCount++;
    if (runCount == 300) {
      console.log(outputString);
      outputString = "";
      runCount = 0;
    }
    show = !show;
    frame.attr('visibility', show ? 'visible' : 'hidden');
    frameIndex = 0;
    frameTimes = new Array(frameTimes.length);
  }
});

</script>