アニメーション時の画面再描画はどっちで行う?秒数?フレーム数?

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,955

canvas

score 60

HTML5 Canvasでアニメーションを行いたいのですが、いまいち、FPS(frame per second)の概念であったり、アニメーション表現のための画面再描画の考え方がわかりません。

アニメーションというのは、秒数で行うものなのでしょうか?
それとも、フレーム数で行うものなのでしょうか?

例えば、10秒かけてX軸方向に100px進めさせたいとした場合、
1秒間に10px動かすようにコードをかけば10秒後に100px先に移動しますが、
1秒ごとに10px動かすようなコードだとアニメーションがカックカクになってしまいます。

となると、1秒ごとにというよりは、0.1秒ごとにとかもっと細かい単位で再描画を行うなり、
1フレーム毎に再描画を行うなりするという発想が必要になってくるのですよね?

かなり混乱していて質問がまとまらないのですが、例えば5秒後に指定のオブジェクトを100px先に移動させるアニメーションを実現するコードを書くという発想は不適切でしょうか?

「xxx秒後に」という秒を基準にした考えではなく、「xxxフレーム後に」というフレームを基準に考えるべきですか?

かなり混乱していてまとまりがないので、自分がわかっていることとわかっていないことの切り分けを以下にリストアップしてみます。

 わかっていることの整理

  • FPSとは一秒間のフレーム数。60FPSは1秒間に60回、画面再描画を行うみたいなこと。
  • マシーンの性能によって処理性能は異なるため、マシーンによって最適なFPSは異なる
  • setTimeoutは指定した時間間隔で処理を実行してくれるが、ブラウザが再描画出来る状態になっていなくても処理を実行してしまう
  • 逆にrequestAnimationFrameはブラウザが再描画出来る状態に処理を実行してくれるが、時間間隔は変動する

 わかっていないことの整理

  • 何秒かけて始点から終点に移動させるというコードをどう書いて良いかわからない。わからない原因はFPS周りのところで混乱しているため。
  • アニメーションは秒数を基準に考えるべきなのか?フレーム数を基準に考えるべきなのか?
  • フレーム数を基準に考えた場合、実際のFPSは変動するから、その影響を考慮する必要があるのか?考慮する場合はどういうことを気にする必要があるのか?

 コード

まだcanvasもcanvas animationもよく理解していないので無理やり書いたコードで汚いですが、一応掲載します。

setTimeoutを使って画面再描画を行う場合のDEMO
requestAnimationFrameを使って画面再描画を行う場合のDEMO

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

var circle = new Circle(15, 15, 15);

(function loop() {
    context.clearRect(0, 0, canvas.width, canvas.height);
    circle.moveBy(5, 0);
    draw(circle);

        //setTimeoutを使う場合 
    //setTimeout(loop, 1000 / 60);

         //requestAnimatinFrameを使う場合
    //requestAnimationFrame(loop);
})();


function draw(circle) {

    context.beginPath();
    context.arc(circle.x(), circle.y(), circle.r(), 0, Math.PI*2, false);
    context.fill();

}


function Circle(x, y, radius) {

    var _x = x;
    var _y = y;
    var _r = radius;

    this.x = function() {
        return _x;
    }

    this.y = function(){
        return _y;
    }

    this.r = function() {
        return _r;
    }

    this.moveBy = function(x, y) {
        _x = _x + x;
        _y = _y + y;
    }

}

 追記

Final Cut Pro Xのタイムラインを見ると、フレーム数が基準になっているようでした。
自分がよく使う設定では30pになっていて30フレームで1秒になる設定でした。
となると、アニメーションの基準として考えるのはフレームということですかね。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+2

アニメーションは秒数を基準に考えるべきなのか?フレーム数を基準に考えるべきなのか?

普通FPSを意識する事なんて、格ゲーやFPS等の1フレームの動作の遅延が勝敗を影響するゲームくらいでしかないですよね?
「例えば、10秒かけてX軸方向に100px進めさせたいとした場合」のように基本的に人間が扱う単位は秒なので、秒数に従いましょう。

フレーム数を基準に考えた場合、実際のFPSは変動するから、その影響を考慮する必要があるのか?考慮する場合はどういうことを気にする必要があるのか?

気にする必要があります。

例えばウィルス対策ソフトが裏でファイルスキャンを始めたりして遅くなった場合、
ブラウザーはマシンをフリーズさせない為にFPSを落として描画する事があります。
他にもChromeではバックグラウンドに居る場合、1FPS程度に描画の更新頻度を落として負荷を減らす実装になっています。

何秒かけて始点から終点に移動させるというコードをどう書いて良いかわからない。
わからない原因はFPS周りのところで混乱しているため。

jQuery3や、Velocity.jsというアニメーション専用のライブラリの、アニメーション周りのソースコードをざっと読んだ事があります。
その意訳を下記に記載します(ホントかどうか実際にソースコード読んでみてください)

5秒掛けて黒丸が100px移動するアニメーション関数loopを実装した前提で記載します。

  1. 今の時刻(何時何分何秒)を拾得して変数として保存
  2. loop関数が呼ばれたら、今の時刻と1の時刻のdiffを取る
  3. diffを取った結果、2800ms経過していた場合、100px / 5000ms * 2800ms = 56px進んでいるべきという事が分かる
  4. 黒丸を56pxの場所に再設置する
  5. 5秒過ぎていたら終了、それ以前ならばrequestAnimationFrame(loop);を再度実行

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/14 16:01

    詳しい解説ありがとうございます!すぐには理解出来ないので、ちょっと読み込んでみます。またコメントさせて頂きます。ありがとうございます!

    キャンセル

  • 2016/08/14 19:29

    大変参考になりました。ご掲載いただいた実装例もすっと理解出来ました。その例であればrequestAnimationFrameが変動するフレームレート下で毎フレーム再描画するとしても、秒数を基準にアニメーションを組めますね!!!Velocity.jsは以前、一通りの機能を遊びで試したことはあります。コードは5000行くらいとのことですが移動中にタブレッドでコツコツと読んでみたいと思います!ありがとうございました!!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.21%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる