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).
| license: gpl-3.0 |
| <!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> |