[26] [DFN[[RUBYB[[[アニメーションフレームコールバック]]]@en[animation frame callback]]]]は、
[[レンダリングの更新]]のタイミングで呼び出される[[コールバック]]です。
[[スクリプト]]による[[アニメーション]]効果の実装のために使うことができます。
[CODE(DOMi)@en[[[Window]]]] [[オブジェクト]]の
[DFN[[CODE(DOMm)@en[[[requestAnimationFrame]]]]]] [[メソッド]]は[[アニメーションフレームコールバック]]を登録し、
[DFN[[CODE(DOMm)@en[[[cancelAnimationFrame]]]]]] [[メソッド]]は削除します。

* 仕様書

[REFS[
- [11] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2014-11-21 03:08:35 +09:00]] 版) <https://html.spec.whatwg.org/#animation-frames>
]REFS]

* アニメーションフレームコールバック

[12] [DFN[[RUBYB[[[アニメーションフレームコールバック]]]@en[animation frame callback]]]]は、
[[イベントループ]]で[[レンダリング]]が更新される際に実行される[[コールバック]]です。
任意の [[JavaScript関数]]を使うことができます。

[25] [[アニメーションフレームコールバック]]は、実行時、
[[引数]]として[[現在時刻]]を受け取ります。

;; [43] 正確には、[[レンダリングの更新]]開始時点の [CODE(DOMi)@en[DOMHighResTimeStamp]]
です。

[22] [DFN[[RUBYB[アニメーションフレームコールバックの実行]@en[run the animation frame callbacks]]]]は、
[VAR[対象]]と[[時刻印]][VAR[今]]について、次のようにします
[SRC[>>11]]。

[FIG(steps)[
= [39] [VAR[写像]]を、[VAR[対象]]の[F[アニメーションフレームコールバックの写像]]の複製に設定します。
= [40] [VAR[対象]]の[F[アニメーションフレームコールバックの写像]]を、
新しい[[順序付き写像]]に設定します。
= [41] [VAR[写像]]の各[VAR[コールバック]]について、[[順に][for each]]、
== [42] [VAR[コールバック]]について[[コールバック関数の呼び出し]]を実行します。
[VAR[今]]を[[引数]]とします。[[例外]]が[[投げ]]られたら、
[[例外の報告]]をします。
]FIG]

;; [23] [[アニメーションフレームコールバックの実行]]は、
[[レンダリングの更新]]の過程で呼び出されます。
[SEE[ [[レンダリングの更新]]、[[イベントループ]] ]]

;; [24] [[コールバック]]の実行途中で[[コールバック]]を追加したり削除したりしても、
実行には影響しません。 [SRC[>>11]]

;; [29] [[コールバック]]から[[一時停止]]や[[スピン]]を呼び出した場合どうなるのかは不明です。

** 文脈

[50] 
[CODE[Window]] [[インターフェイス]]と
[CODE[DedicatedWorkerGlobalScope]] は、
[[interface mixin]]
[DFN[[CODE[AnimationFrameProvider]]]]
を[[実装]]しています [SRC[[CITE[HTML Standard]]]]。

[51] 
[CODE[AnimationFrameProvider]] は、
[CODE[requestAnimationFrame]]
と
[CODE[cancelAnimationFrame]] の2つの[[メソッド]]を持ちます
[SRC[[CITE[HTML Standard]]]]。

;;
つまりこの2つの[[メソッド]]は、
[[文書環境]]と[[専用ワーカー]]では使えますが、
[[共有ワーカー]]や[[サービスワーカー]]や[[ワークレット]]では使えません。

[53] 
[CODE[AnimationFrameProvider]]
[VAR[オブジェクト]]が[DFN[[F[[RUBYB[対応中]@en[supported]]]]]]とは、
次の''いずれか''でも[[真]]であることをいいます [SRC[[CITE[HTML Standard]]]]。

[FIG(list)[
- [54] 
[VAR[オブジェクト]]が [CODE[Window]] である
- [55] 
[VAR[オブジェクト]]の[F[所有者集合]]が [CODE[Document]] を[[含む][list contains]]
- [56] 
[VAR[オブジェクト]]の[F[所有者集合]]が[F[対応中]]である
[CODE[DedicatedWorkerGlobalScope]] を[[含む][list contains]]
]FIG]

;; [70] つまり、[[共有ワーカー]]から[[専用ワーカー]]を作っても、
[CODE[requestAnimationFrame]] は使えません。

[52] 
[CODE[AnimationFrameProvider]] は、
[DFN[[F[[RUBYB[対象オブジェクト]@en[target object]]]]]]を持ちます。
[CODE[Window]] の[F[対象オブジェクト]]は[F[[[関連付けられた[CODE[Window]]]]]]、
[CODE[DedicatedWorkerGlobalScope]] の[F[対象オブジェクト]]はそれ自身です。
[SRC[[CITE[HTML Standard]]]]

-*-*-

[13] [[対象オブジェクト]]は[[順序付き写像]]である[DFN[[F[[RUBYB[アニメーションフレームコールバックの写像]@en[map of animation frame callbacks]]]]]]
(旧[DFN[[F[[RUBYB[[[アニメーションフレームコールバックのリスト]]]@en[list of animation frame callbacks]]]]]]
を有します。初期状態では空です。 [SRC[>>11]]
このリストに登録された[[コールバック]]が[[アニメーションフレームコールバック]]として実行されます。


** アニメーションフレームコールバック識別子

[14] [[アニメーションフレームコールバックのリスト]]に登録された[[コールバック]]には識別子が割り振られます。この識別子を使って[[アニメーションフレームコールバック]]の登録を解除できます。

[15] [[対象オブジェクト]]は[DFN[[F[[RUBYB[[[アニメーションフレームコールバック識別子]]]@en[animation frame callback identifier]]]]]]を持ちます。
初期値は0です。 [SRC[>>11]]
この値は最後に割り当てられた識別子を表していて、[[コールバック]]が登録される度に[[インクリメント]]されていきます。

* [CODE(DOMm)@en[requestAnimationFrame]]

[16] 
[DFN[[CODE(DOMm)@en[[[requestAnimationFrame]]]]]] [[メソッド]]は、
次のようにしなければ[MUST[なりません]] [SRC[>>11]]。

[FIG(steps)[
= [57] [VAR[コールバック]]を、第1引数を
[CODE[FrameRequestCallback]] として解釈した結果に設定します。
= [58] 
[[文脈オブジェクト]]の[F[対応中]]が[[偽]]の場合、
== [59] 
[CODE[NotSupportedError]] [CODE[DOMException]]
を[[投げ]]、ここで停止します。
= [60] 
[VAR[対象]]を、
[[文脈オブジェクト]]の[F[対象オブジェクト]]に設定します。
= [61] 
[VAR[対象]]の[F[アニメーションフレームコールバック識別子]]を
[N[1]] [[インクリメント]]します。
= [62] 
[VAR[ハンドル]]を、[VAR[対象]]の[F[アニメーションフレームコールバック識別子]]に設定します。
= [63] 
[VAR[対象]]の[F[アニメーションフレームコールバックの写像]] [ [VAR[ハンドル]] ] を、
[VAR[コールバック]]に[[設定][map set]]します。
= [64] 
[VAR[ハンドル]]を [CODE[unsigned long]] として返します。

]FIG]

[21] [[コールバック]]が既に当該[[文書]]のリスト (や他のリスト) 
に含まれているかどうかはチェックしません。同じ[[コールバック]]が複数回登録されれば、
その回数だけ実行されることとなります。

* [CODE(DOMm)@en[cancelAnimationFrame]]

[19] 
[DFN[[CODE(DOMm)@en[[[cancelAnimationFrame]]]]]] [[メソッド]]は、
次のようにしなければ[MUST[なりません]] [SRC[>>11]]。

[FIG(steps)[
= [17] [VAR[ハンドル]]を、
第1引数を [CODE[unsigned long]] と解釈した結果に設定します。
= [18] 
[[文脈オブジェクト]]の[F[対応中]]が[[偽]]の場合、
== [65] 
[CODE[NotSupportedError]] [CODE[DOMException]]
を[[投げ]]、ここで停止します。
= [66] 
[[文脈オブジェクト]]の[F[対象オブジェクト]]の[F[アニメーションフレームコールバックの写像]] [ [VAR[ハンドル]] ]
を[[削除][map remove]]します。

]FIG]

[20] この[[メソッド]]は、与えられた識別子
([CODE[requestAnimationFrame]] の返り値) の[[コールバック]]があれば、
これをリストから削除します。なければ何もしません。
同じ[[コールバック]]が複数回登録されていたとしても、
削除されるのは識別子が一致するもの1つだけです。

* 処理

[45] [[コールバック関数]]の呼び出しについては、[[レンダリングの更新]]を参照。

* 関連

[35] [CODE(JS)@en[[[setTimeout]]]] も[[アニメーション]]に使えますが、
[[Webブラウザー]]の描画のタイミングとは独立しています。より適切なタイミングで[[アニメーション]]処理を実行できるよう、
[CODE(DOMm)@en[[[requestAnimationFrame]]]] が追加されました [SRC[>>32]]。

* 歴史

** 誕生

[REFS[
- [33] [CITE[JS Animation API - Google グループ]] ([TIME[2015-02-08 15:37:46 +09:00]] 版) <https://groups.google.com/forum/#!topic/mozilla.dev.platform/Un0M7bmw338>
- [34] [CITE@en[Re: solving the CPU usage issue for non-visible pages]] ([[Robert O'Callahan]] 著, [TIME[2009-10-20 06:51:53 +09:00]] 版) <https://lists.w3.org/Archives/Public/public-webapps/2009OctDec/0226.html>
- [32] [CITE[Well, I'm Back: mozRequestAnimationFrame]] ([TIME[2015-02-02 17:16:03 +09:00]] 版) <http://robert.ocallahan.org/2010/08/mozrequestanimationframe_14.html>
]REFS]

**

[1] [CITE[Timing control for script-based animations]]
( ([TIME[2012-02-21 23:13:03 +09:00]] 版))
<http://www.w3.org/TR/2012/WD-animation-timing-20120221/>

[2] [CITE[Timing control for script-based animations]]
( ([TIME[2012-03-01 22:02:03 +09:00]] 版))
<http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/RequestAnimationFrame/Overview.html>

[3] [CITE@en[871318 – Image slideshow on Instagram profiles is broken with NS_ERROR_XPC_NOT_ENOUGH_ARGS: Not enough arguments ''''''[''''''nsIDOMWindow.requestAnimationFrame'''''']'''''']]
( ([TIME[2013-05-18 16:12:35 +09:00]] 版))
<https://bugzilla.mozilla.org/show_bug.cgi?id=871318>

[4] [CITE[Timing control for script-based animations]]
( ([TIME[2013-10-31 06:01:47 +09:00]] 版))
<http://www.w3.org/TR/2013/CR-animation-timing-20131031/>

[5] [CITE[''''''[''''''whatwg'''''']'''''' Proposal: requestBackgroundProcessing()]]
( ([TIME[2014-02-20 21:38:44 +09:00]] 版))
<http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2014-February/042075.html>

[6] [CITE[Timing control for script-based animations]]
( ([TIME[2014-07-31 14:26:06 +09:00]] 版))
<https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/RequestAnimationFrame/Overview.html>

** HTML Standard への統合

[7] [CITE[IRC logs: freenode / #whatwg / 20140917]]
( ([TIME[2014-09-18 04:45:19 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20140917#l-1244>

[8] [CITE@en[Re: Animation frame task]]
( ([[James Robinson]] 著, [TIME[2014-08-22 15:07:50 +09:00]] 版))
<http://lists.w3.org/Archives/Public/www-dom/2014JulSep/0091.html>

[9] [CITE@en[''''''[''''''whatwg'''''']'''''' Move RequestAnimationFrame steps into HTML?]]
( ([[James Robinson]] 著, [TIME[2014-09-18 07:44:16 +09:00]] 版))
<http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Sep/0046.html>

[10] [CITE[IRC logs: freenode / #whatwg / 20141119]]
( ([TIME[2014-11-21 01:19:37 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20141119#l-819>

[REFS[
- [27] [CITE@en[Web Applications 1.0 r8849  Flesh out how rendering happens in the event loop. This also defines requestAnimationFrame() and obsoletes the 'Timing control for script-based animations' spec (by request of that spec's editors)]] ([TIME[2014-11-20 06:56:00 +09:00]] 版) <https://html5.org/r/8849>
- [30] [CITE@en[Web Applications 1.0 r8850 Teach the event loop that it might not have a task to run]] ([TIME[2014-11-20 07:20:00 +09:00]] 版) <https://html5.org/r/8850>
- [31] [CITE@en[Web Applications 1.0 r8880 Fix callback logic to reference Web IDL and use the right conventions.]] ([TIME[2015-01-16 05:52:00 +09:00]] 版) <https://html5.org/r/8880>
]REFS]

[28] >>27 で[[アニメーションフレームコールバック]]の仕様は単独の仕様書から
[[HTML Standard]] に移動されました。

;; [[レンダリングの更新]]も参照。

[36] [CITE@en[Define FrameRequestCallback · whatwg/html@7308390]]
([TIME[2015-08-28 16:38:06 +09:00]] 版)
<https://github.com/whatwg/html/commit/73083902d57ec68058b31e2c6acc7ebd1cf334cc>

[37] [CITE@en[Fix #96: change requestAnimationFrame type to unsigned long · whatwg/html@23cf780]]
([TIME[2015-09-07 12:48:07 +09:00]] 版)
<https://github.com/whatwg/html/commit/23cf780116ba53168748c243989b357c0a4d337b>

[38] [CITE[Timing control for script-based animations]]
([TIME[2015-09-17 04:21:29 +09:00]] 版)
<http://www.w3.org/TR/2015/NOTE-animation-timing-20150922/>

[44] [CITE[javascript - Safari and requestAnimationFrame gets DOMHighResTimestamp; window.performance not available - Stack Overflow]]
( ([TIME[2016-06-20 13:06:51 +09:00]]))
<http://stackoverflow.com/questions/23298569/safari-and-requestanimationframe-gets-domhighrestimestamp-window-performance-no>

[46] [CITE@en[Background Tabs in Chrome 57  |  Web  |  Google Developers]]
([TIME[2017-03-14 09:42:32 +09:00]])
<https://developers.google.com/web/updates/2017/03/background_tabs>

[FIG(quote)[
[FIGCAPTION[
[47] [CITE[Release Notes for Safari Technology Preview 28 | WebKit]]
([TIME[2017-05-04 02:12:59 +09:00]])
<https://webkit.org/blog/7516/release-notes-for-safari-technology-preview-28/>
]FIGCAPTION]

> requestAnimationFrame callbacks are now throttled to 30fps and aligned in cross-origin iframes (r215070, r215153)

]FIG]


[48] [CITE@en[Update references to requestAnimationFrame to point to HTML spec]]
([[birtles]]著, [TIME[2017-12-04 10:39:18 +09:00]])
<https://github.com/w3c/web-animations/commit/6d9fd5f84b4fe3e524a8bbf073705f0b944a863b>

[49] [CITE@en[Add requestAnimationFrame() in workers]]
([[fserb]]著, [TIME[2018-08-28 01:02:51 +09:00]])
<https://github.com/whatwg/html/commit/3d9b41d1086131f21cd87a1957344a6fdb7e1748>

[67] [CITE@en[OffscreenCanvas new commit solution · Issue #3587 · whatwg/html]]
([TIME[2018-09-21 23:50:13 +09:00]])
<https://github.com/whatwg/html/issues/3587>

[68] [CITE@en[OffscreenCanvasAnimation/OffscreenCanvasAnimation.md at 2e0546417d4f45d194270a67a1cdf303f2e0ef88 · junov/OffscreenCanvasAnimation]]
([TIME[2018-09-21 23:51:42 +09:00]])
<https://github.com/junov/OffscreenCanvasAnimation/blob/2e0546417d4f45d194270a67a1cdf303f2e0ef88/OffscreenCanvasAnimation.md>

[69] [CITE@en[Worker.requestAnimationFrame spec by fserb · Pull Request #3677 · whatwg/html]]
([TIME[2018-09-21 23:52:23 +09:00]])
<https://github.com/whatwg/html/pull/3677>

[71] [CITE@en[Meta: wrap IDL block in <code> for consistency]]
([[foolip]]著, [TIME[2018-09-06 00:44:33 +09:00]])
<https://github.com/whatwg/html/commit/712a053a576525873156e8e4d405fd0443074610>

[72] [CITE@en[Meta: wrap IDL block in <code> for consistency by foolip · Pull Request #3990 · whatwg/html]]
([TIME[2018-09-29 17:36:02 +09:00]])
<https://github.com/whatwg/html/pull/3990>

[73] [CITE@en[Memorandum of Understanding Between W3C and WHATWG]]
([TIME[2019-05-28 17:23:37 +09:00]])
<https://www.w3.org/2019/04/WHATWG-W3C-MOU.html>

[74] [CITE@en[Update autofocus processing algorithm by tkent-google · Pull Request #4763 · whatwg/html]]
([TIME[2020-08-31 17:52:13 +09:00]])
<https://github.com/whatwg/html/pull/4763>