理解できたらいいな・・。
だいぶ今さら感はあるのですが、改めて知っておきたいタイミングなので。
一定間隔で処理を繰り返す
CanvasでもCssアニメーションでも、「描画処理を繰り返し実行する」ところは一緒。
そこをどうやって実装するかという話で、今まではsetIntervalやsetTimeoutを再帰で呼んだりしてました。
setInterval
var anim = function() { console.log('Animations here.'); }; window.setInterval(anim, 1000);
一番わかりやすいし手軽です。
だいたいいつもコレなんじゃないでしょうか。
setTimeout
var anim = function() { console.log('Animations here.'); }; (function animLoop(){ anim(); window.setTimeout(animLoop, 1000); }());
setTimeoutだけでも一定間隔での実行は可能です。
ただちょっとわかりにくいですね・・。
requestAnimationFrame
var anim = function() { console.log('Animations here.'); }; (function animloop(){ anim(); window.requestAnimationFrame(animloop); }());
記述としては、setTimeoutとほぼ同じです。
違うところは、実行間隔を指定する引数がないところ。
記述は似ているものの、全然違うところがあります。
実行間隔が指定できないあたり、もうピンときてるかもですが・・。
実行間隔はブラウザまかせ
そうなんです。
MDNによると、
この再描画はフォアグラウンドのタブでおよそ毎秒60回行われるとされています。
しかし、バックグラウンドのタブではより少ない割合に減らされるでしょう。
ようは、厳密な実行間隔は指定できないものの、
- 毎秒"およそ"60回(60FPSで)実行される
- ブラウザの負荷にあわせて、描画準備ができ次第、適宜実行される
- ブラウザがアクティブでない間は、実行回数が自動で低下されメモリ節約
あらためてコードを並べて載せておくと、
var anim = function() { console.log('Animations here.'); }; // 1. setInterval window.setInterval(anim, 1000 / 60); // 2. setTimeout (function animLoop(){ anim(); window.setTimeout(animLoop, 1000 / 60); }()); //3. requestAnimationFrame (function animloop(){ anim(); window.requestAnimationFrame(animloop); }());
以上の3つは、だいたい同じ結果になるということ。
だいたい。
実用的なのか
まずは世間の状況を。
ブラウザの対応状況
私めの主戦場、スマートフォンという名のモバイル環境はと言いますと、
iPhone5sさまのおかげでiOS7がどばっと増えることが予想できるので、まぁナシではないかな・・。
にしてもAndroidはもう・・。
というわけで
個人の意見にはなりますが、全然使えるところでは使って良いと思ってます。
"そこまで厳密に実行間隔を意識しなくてもよい"のであれば、setIntervalやsetTimeoutの代わりに使うべきなのかなーと。
もちろん、コードを書く上での制約も生まれます。
- setIntervalは記述が若干異なるため使えない
- iOS6以降しか恩恵を受けられない
ここは事前のお約束なのかなーとも。
おまけ
実際に使う場合のコードサンプルとかメモとかそういうの。
定義するとこ
(function (w, r) { w['r'+r] = w['r'+r] || w['webkitR'+r] || w['mozR'+r] || w['msR'+r] || w['oR'+r] || function(c){ w.setTimeout(c, 1000 / 60); }; })(window, 'equestAnimationFrame');
これはこちらのスライドから拝借したスニペットですが、スッキリ書けて良いですね。
アニメーションのとこ
2秒に一回実行したい処理の場合は、
var interval = 2000, anim = (function(){ var i = 0, timing = interval / 1000 * 60; return function() { if (i % timing === 0) { console.log('Animations here.' + i); } i++; }; }()); (function animloop(){ anim(); window.requestAnimationFrame(animloop); }());
FPS前提に慣れてない身としては、こういう風にしないと使えないのです・・。
もっとも、正確にやる必要のある場合は、以下リンクみたくするのがいいのかしら。
この分野の最前と自分との差が半年以上ってところがグッとくるわねー。