ded / morpheus

A Brilliant Animator
504 stars 57 forks source link

Broken in iOS 7 & developer builds of safari #53

Closed CiiDub closed 10 years ago

CiiDub commented 10 years ago

Animations run in a loop in the newest dev. Builds of Safari & mobile safari 7. Check the examples page. http://ded.github.io/morpheus/

MAZ-001 commented 10 years ago

Same here. window.performance is not supported, so the timestamp is not updated (line 105). But in tween() and tween()>run() the delta is calculated by the argument passend to requestAnimationFrame and the time the tween-method was called. It works when the condition in line 105 is removed. This would update the timestamp regardless of window.performance. But I don't know if that change breakes compatibility with other browsers.

ded commented 10 years ago

doh. alright. i'll have a look

MAZ-001 commented 10 years ago

I think it has to do with requestAnimationFrame.

In render(): If window.performance timing is possible it is always passing a timestamp to the callback. But the callback works only if the argument to the callback is a timestamp. duration = currentTime-startTime

If window.performance is not available it has to work with the default time passed to the render-callback. But that is not a full timestamp. Here is a fiddle to see the default argument for the animation-callback: http://jsfiddle.net/bcnmE/4/

The current version works in two cases: a) requestAnimationFrame is available + window.performance is available or b) requestAnimationFrame is NOT available + window.performance is NOT available

but requestAnimationFrame is availeble + window.performance is NOT available == broken

I think the "solution" in my previous comment does the job. The result from the mapped "now()" is not less accurate as the default argument for the callback ... I think. :)

karlwestin commented 10 years ago

thanks for reporting this issue! this is the fix i ended up using for now, making a check to see if the timestamp and now() produces similar results, and if not, updating the timestamp

  var matchingTimestamps;
  frame(function(timestamp) {
    // if we're using a high res timer, make sure timestamp is not the old epoch-based value.
    // http://updates.html5rocks.com/2012/05/requestAnimationFrame-API-now-with-sub-millisecond-precision
    // patch for https://github.com/ded/morpheus/issues/53
    // check if timestamps are on the same scale and cache result
    var argument = timestamp > 1e12,
        getTime = now() > 1e12;
    matchingTimestamps = argument === getTime;
  });

  function render(timestamp) {
    var i, count = children.length
    if (!matchingTimestamps) timestamp = now()
    for (i = count; i--;) {
      children[i](timestamp)
    }
    children.length && frame(render)
  }

i've tested this fix in: win: IE 8, 9, 10 Chrome 29

Mac Firefox 23, 24 Webkit r156732 (version showing this bug) Safari 6.0.5

iOS 6, 7 (version showing this bug)

RwwL commented 10 years ago

@MAZ-001 I don't think this is quite correct:

requestAnimationFrame is availeble + window.performance is NOT available == broken

... because window.performance doesn't seem to be available in iOS 6 (according to the fiddle you posted) but requestAnimationFrame is available (as webkitRequestAnimationFrame), and it works. Also, did you mean line 100 instead of 105 re: the conditional check you might be able to drop to work around this? In the current src 105 is just the closing bracket for render(). Time to go try it out, I guess...

karlwestin commented 10 years ago

the difference between iOS6 and iOS7 is that the prefixed webkitRequestAnimationFrame calls the callback with a millisecond times (starting 1970), while the unprefixed in iOS 7 calls the callback with sub-millisecond timer (time since page load if i remember correctly)