Question

I created an animation using requestAnimationFrame. Works fine in Windows Chrome and IE; Safari (tested Safari 6 and 7) breaks. It turns out that rAF get a DOMHighResTimestamp rather than a Date timestamp. That's all fine and good, and what I expected, as it's now part of the spec. However, as far as I've been able to find, there's no way to get the current DOMHighResTimestamp (i.e. window.performance is not available, even with a prefix). So if I create the start time as a Date timestamp, it behaves radically wrong when I try to determine progress within the rAF callback (very small negative numbers).

If you look at this JSBin on Safari, it won't animate at all.

In this JBin, I've made a change to "skip" the first frame (where the time parameter is undefined), so that startTime gets set to the time parameter on the next frame. Seems to work, but skipping a frame seems a bit crappy.

Is there some way to get the current DOMHighResTimestamp in Safari, given the lack of window.performance? Or alternately, force rAF into some sort of legacy mode that forces it to get a Date timestamp instead?

Does anyone know why Safari has this inconsistency, where it provides the parameter in a format that you can't get at any other way?

Was it helpful?

Solution

Performance.now() is only a recommendation as of now. https://developer.mozilla.org/en-US/docs/Web/API/Performance.now() I can only assume it's a matter of time before it's official, seeing as how everyone but Safari has it built in.

Besides that fact use this to your advantage. Since you know requestAnimationFrame returns a DOMHighResTimestamp use that for your timing.

Game.start = function(timestamp){
    if(timestamp){
        this.time = timestamp;
        requestAnimationFrame(Game.loop);
    }else{
        requestAnimationFrame(Game.start);
    }
}

Game.loop = function(timestamp){
    Game.tick(timestamp);
    ... your code
    requestAnimationFrame(Game.loop);
}

Game.tick = function(timestamp) {
    this.delta      = timestamp - this.time;
    this.time       = timestamp;
};

What I do here, is call Game.start which will begin the loop (I've run into situations where the timestamp was undefined so we try until we get something valid). Once we get that we have our base time and since RAF is going to return a timestamp our tick function never has to call Date.now or performance.now as long as we pass it the timestamp returned by requestAnimationFrame.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top