Yahoo!ウィジェット の作り方 (4) - インターバルとアニメーション

LingrTickr - 誰でもニコニコメソッドプレゼン
http://labs.cybozu.co.jp/blog/nakatani/2007/05/lingrtickr.html

Yahoo!ウィジェットでもう一つ作ってみた。
Lingr でチャットした内容がニコニコ動画のように画面を流れるというツール。


と、この前最終回と言っておきながら。
LingrTickr を作る中でせっかくアニメーション周りの機能に触ったのでそのあたりをちらっとまとめておく。
まあまあ、コンテスト締め切られたからもういらないなんて言わずに(笑)。

アニメーション

JavaScript でアニメーション的効果を行いたいと思ったら、(script.aculo.us 等のライブラリ類を利用するのでなければ) setTimeout や setInterval を使うのが一般的だろう。
が、残念ながら Yahoo! Widgets ではこれらはサポートされていない。まあブラウザの window オブジェクトがないのでいたしかたないことではあるのだが。

その代わりに timer オブジェクトと animator オブジェクトがあって、これらはそこそこいい感じ。
この timer オブジェクトはリファレンスでは触れられていないものの、var timer = new Timer() などとすれば動的に生成できるので、がんばれば setInterval/setTimeout のラッパーが書けそう。

timer

timer は *.kon の中では下記のように定義する。

<timer name="myTimer" interval="60" onTimerFired="ticker();" ticking="true" />

これで60秒ごとに ticker() が実行される。interval の単位はミリ秒ではなく秒なので注意。
定期実行の ON/OFF は、name に指定したオブジェクト名を使って、myTimer.ticking = (true|false) として制御できる。setInterval よりオブジェクト指向っぽくて悪くない。

動的生成する場合はこんな感じか。

  var timer = new Timer();
  timer.interval = 10;
  timer.onTimerFired = function(){ alert("abc"); };
  timer.ticking = true;

/dump timer してみると、name="Timer001" などとしてオブジェクトが定義されていたが、この Timer001 という名前ではオブジェクトにはアクセスできなかった。安心。

すると setInterval/clearInterval もどき(パラメータとか無視)はこんな感じだろうか?

  function setInterval(func, delay) {
    var timer = new Timer();
    timer.interval = delay / 1000;
    timer.onTimerFired = func;
    timer.ticking = true;
    return timer;
  }
  function clearInterval(timer) {
    timer.ticking = false;
  }

……なんかがんばって setInterval を使う必要がないような気がしてきた。
setTimeout の方がまだ喜ばれる?

  function setTimeout(func, delay) {
    var timer = new Timer();
    timer.interval = delay / 1000;
    timer.onTimerFired = function(){timer.ticking=false;if((typeof func)== "function"){func();}else{eval(func)}};
    timer.ticking = true;
    return timer;
  }

  var t = setTimeout( "alert('abc');", 5000 );

setTimeout の返値( timer オブジェクト)を保持しておかないと、タイマーごと破棄されてしまうようだ。微妙。

animator オブジェクト

テキストや画像などのビューオブジェクトをアニメーションさせる機能だが、自分でアニメーションの内容を定義できる CustomAnimation() はあまり嬉しくなさそうだ。
timer オブジェクトで出来ることとなんら変わらず、しかもアニメーションにしてしまうと外からは全体一括でしか動かしたり止めたりの制御ができなくなる。せめて前回呼び出し時から今回呼び出し時に何ミリ秒経過しているかを渡してくれたりでもしたら意義があったと思うのだが。結果的にアニメーションのための処理であることが明示されるということくらい?
というわけで、Yahoo! Widgets のアニメーション機能はあらかじめ用意されているアニメーションを使うときに一番幸せ度が高いように思う。

もともと定義されているアニメーションは MoveAnimation, RotateAnimation, FadeAnimation の3つ。名前通り移動、回転、フェードイン/アウト のアニメーション。こんな感じに使う。

// myImage という画像オブジェクトがあるとする
var anime = new MoveAnimation(myImage, 100, 200, 5000, animator.kEaseNone, function(){alert("done.");});
animator.start(anime);

これで myImage という画像が (100, 200) に「5秒間かけて」移動する。第4引数がアニメーションの更新間隔ではなく終了までの時間で、単位が timer オブジェクトと変わってミリ秒である点が注意なくらいか。