- if (count >= times) return;
- window.requestAnimFrame(function(scheduled_epoch_time_ms) {
- var delay = (scheduled_epoch_time_ms - start_time);
- previous_count = count;
- count = Math.floor(delay / every_ms);
- if ((count - previous_count) > (times / 2)) {
- count = previous_count + (times / 2);
- }
- if (count > times - 1) {
- // Ensure call at max times.
- if (previous_count !== (times - 1)) {
- repeat_fn(times - 1);
- }
- cleanup_fn();
+ if (frameNumber >= maxFrames) return;
+ Dygraph.requestAnimFrame.call(window, function() {
+ // Determine which frame to draw based on the delay so far. Will skip
+ // frames if necessary.
+ var currentTime = new Date().getTime();
+ var delayInMillis = currentTime - startTime;
+ previousFrameNumber = frameNumber;
+ frameNumber = Math.floor(delayInMillis / framePeriodInMillis);
+ var frameDelta = frameNumber - previousFrameNumber;
+ // If we predict that the subsequent repeatFn call will overshoot our
+ // total frame target, so our last call will cause a stutter, then jump to
+ // the last call immediately. If we're going to cause a stutter, better
+ // to do it faster than slower.
+ var predictOvershootStutter = (frameNumber + frameDelta) > maxFrameArg;
+ if (predictOvershootStutter || (frameNumber >= maxFrameArg)) {
+ repeatFn(maxFrameArg); // Ensure final call with maxFrameArg.
+ cleanupFn();