7

Byłem więc dobrym obywatelem sieciowym, używając funkcji wykrywania cech, aby sprawdzić, czy przeglądarka obsługuje requestAnimationFrame i opiera się jedynie na rozwiązaniu opartym na setTimeout (coś podobnego do linii Paul Irish's famous post).requestAnimationFrame przekazuje nieoczekiwane parametry w IE10

var NOW = Date.now || function() { return new Date.getTime(); }; 
var reqAnimFrame = 
     window.requestAnimationFrame || 
     window.webkitRequestAnimationFrame || 
     /*      ... ||      */ 
     function (callback) { 
      setTimeout(function() { callback(NOW()); }, 1000/60); 
     }; 

var previousTime = NOW(); 
function animStep(time) { 
    var timePassed = time - previousTime; 
    myCharacter.move(myCharacter.speed * timePassed); 
    previousTime = time; 
    reqAnimationFrame(animStep); 
} 

// start the animation 
reqAnimationFrame(animStep); 

To działało świetnie wszędzie, dopóki nie pojawił się program Internet Explorer 10. W IE10 przekazany parametr time nie wydaje się mieć nic wspólnego z bieżącym czasem, pomijając obliczenia timePassed.

Co się dzieje?

+0

dość zaskakująco ... to byłby pierwszy raz, gdy * Internet Explorer * odbiega od specyfikacji. Jestem zszokowany! – jAndy

+0

@jAndy Również w tym przypadku można powiedzieć, że są przed innymi przeglądarkami w następujący * * go. – balpha

+0

I to jest właśnie punkt: IE pomieszane przez lata, a teraz próbują być dobrym facetem następujące standardy mocno. Mam nadzieję, że uda się to zrównoważyć w przyszłości. – Sander

Odpowiedz

10

Wszystkie (o ile wiem) inne przeglądarki, które implementują requestAnimationFrame mijają specyfikacji w (w momencie pisania) prąd Working Draft:

Let czas być [czas przerysem] wyrażone jako liczbę milisekund od 1970-01-01T00: 00: 00Z.

To odpowiada czasowi dokładnie tak, jak robisz to NOW().

IE10 jednak goes przez spec w bieżącym Editor's Draft:

Niech czas być wynikiem wywoływanie now method of the Performance interface w tym kontekście.

który zasadniczo oznacza liczbę milisekund ponieważ przeglądarka załadowaniu strony (to znaczy również pomiar jest bardziej precyzyjne, ponieważ performance.now zwrotów milisekund ułamkowe).

I tak, po obliczeniu timePassed po raz pierwszy w IE10, otrzymujesz coś jakby negatywne 43 lata.

Na szczęście, ponieważ wartość przekazana do wywołania zwrotnego requestAnimationFrame ma tę samą jednostkę w każdym przypadku, tylko inny punkt odniesienia, można łatwo dostosować do tego.

Istnieją trzy możliwości:

  1. Można po prostu wyrzucić pierwszy krok animacji, używając go tylko ustawić previousTime, ale nie robi nic innego.
  2. Można zignorować przekazany parametr i za każdym razem używać NOW() (lub performance.now), tym samym mając zawsze ten sam punkt odniesienia.
  3. Albo można zmienić rozpoczęcia animacji to:

    // start the animation 
    reqAnimationFrame(function (t) { 
        previousTime = t - (NOW() - previousTime); 
        animStep(t); 
    ); 
    

    To pozwoli na obliczenie (w tym pierwszym) z timePassed skorygować bez względu Jakie Spec przeglądarka następująco. A ponieważ zmienia tylko pierwsze wywołanie, nie ma też dodatkowego obciążenia w dłuższej perspektywie.