趣味は車輪の再発明♪

javascriptで数値を指定時間内に(なるべく)滑らかに変化させる



数値を指定した時間内に滑らかに変化させる処理のご紹介。アニメーション的な処理を書くときに必要になりますよね。

jQueryで超簡単に使えるスクロールバープラグイン」のサンプルで、おまけの[自動で動かす]ボタンのために作成したものです。 あのボタンの処理ではスクロールバーのつまみを同時に三つグイーンと動かすのですが、あれ、jqueryのanimate()では無理なんです。 animateはstyleの値にしか使えなくて、スクロール量のように要素の属性(scrollLeftやscrollTop)には対応してないんですね。 仕方が無いので、animateと同じように動く関数を作りました。指定時間内にできる限りスムーズに値を変化させます。

作ったあとで、jquery.easingというプラグインの存在を知ったのだけど、いまいち使い方がわからなかったのでまーいいかとw

サンプル

下のボタンを押すと下のボックスの透明度が連続的に変化します。(あまりいいのが思いつかなかったw)

サンプルのHTML

<div style="border:solid 1px black;">
	<div id="screen"></div>
</div>
<button id="btnSample">押してね!</button>

サンプルのJAVASCRIPT

$(function(){
  $("#btnSample").click(function(){
    $(this).css("disabled", true);
    var s = 1;
    var e = 0;
    if($("#screen").css("opacity") == "0") {
      s = 0;
      e = 1;
    }
    easing(s,e,3000,
        function(opacity){
          var strOpa = "0.000";
          if(opacity == 0.0 || opacity == 1.0) {
            strOpa = "" + opacity + ".000"
          } else {
            strOpa = "" + Math.round(opacity * 1000) / 1000 + "000";
            strOpa = strOpa.substring(0,5);
          }
          opacity = Math.round(opacity * 1000) / 1000;
          $("#screen")
            .css("opacity",opacity)
            .text("opacity:" + strOpa + ";");
        },
        function(value){
          $(this).css("disabled", false);
        }
    );
  });
});

easing.js

開始時刻を覚えておいて定期的に呼び出されたときの時刻と比較して値を決定し、ハンドラを呼び出すということ。javascriptではミリ秒単位で時刻を取得できるので、それなりにスムーズです。

単純にインターバルタイマーの間隔を足しこんで指定時間になるまで繰り返すというやり方(つまり回数固定)では処理時間の分だけ長くなっちゃうんですよね。

使い方とかは以下のソースを参照。

/**
 * 値を時間内になだらかに変化させハンドラを呼び出す。
 * 呼び出し回数は状況によって変化する。
 *
 * @param sValue 開始値
 * @param eValue 最終値
 * @param duration 実行時間
 * @param onValueChange 値の変更ハンドラ
 * @param onComplete 終了ハンドラ
 */
function easing(sValue, eValue, duration, onValueChange, onComplete) {
  var t0 = (new Date()).getTime(); //開始時刻(ミリ秒単位)
  var T = duration;     //実行時間(ミリ秒単位)
  //インターバルタイマの開始
  var tid = window.setInterval(function() {
    //現在までの経過時間(ミリ秒単位)
    var t = (new Date()).getTime() - t0;
    //経過時間から現在値の算出
    var value = (eValue - sValue) * t / T + sValue;
    //実行時間が過ぎているなら値は終了時の値とする。
    if(t >= T) {
      value = eValue;
    }
    //値の変更ハンドラを呼び出す
    onValueChange.call(null, value);
    //終了判定
    if(t >= T) {
      //インターバルタイマのキャンセル
      window.clearInterval(tid);
      //完了時の処理を呼び出す(指定されていれば)
      if(onComplete) {
        onComplete.call(null, eValue);
      } else {
        //値の変更ハンドラを呼び出す
        onValueChange.call(null, value);
      }
    }
  }, 1);//1ms間隔で実行
}


RSS Feed Widget
javascriptで数値を指定時間内に(なるべく)滑らかに変化させる
(http://bicycle.life.coocan.jp/takamints/index.php/techtips/easing)
by Koji Takami ( email: vzg03566@gmail.com, GitHub: takamin )