animator.jsの使い方
最近はアリエルの若きJavaScriptマスターの後を追いかけてばかりです。先日、animator.jsを教えてもらいました。他のJavaScriptライブラリより良くできていると思います。
以前、scriptaculousで須崎メソッドを実装しました(http://dev.ariel-networks.com/Members/inoue/suzaki-method)。結局、scriptaculousをAirOneの配布に含めていないので、須崎メソッドは動いていません。今回、animator.jsで再実装しました。今度は、次のメジャーリリースに入ります。
簡単な例を使ってanimator.jsの使い方を説明します。
次のようなbody要素のHTMLを考えます。id="target"の要素を上下に振動させます。
<body onload="init();"> <div style='position:absolute; top:200px'>---200---</div> <div id="target">moving...</div> </body>
magic numberが多いですが、最も簡単なコードは次のようになります。
var t = $('target'); t.style.position = 'absolute'; t.style.top = '200px'; var anim = new Animator({duration: 4000, interval:40, transition: Animator.tx.linear}); anim.addSubject(function (v) { var h = 200 + Math.round(100 * Math.sin(v * 2*Math.PI)); t.style.top = h + 'px';}); anim.play();
最初に、id="target"の要素のpositionスタイルをabsoluteにします。上下に振動させるためにすべきことは、タイマーでt.style.topの値を変更することです。
duration:4000はアニメの長さです(単位はミリ秒)。interval:40はアニメの間隔です(同じく単位はミリ秒)。つまり、上の設定では40msごとのタイマーイベントが100回起きて、4秒すると止まります。
animator.jsの基本は、タイマーのイベントハンドラに、0から1の間の値を取る数値(以下、カウンタ)が渡ることです。transition:Animator.tx.linearの設定で、カウンタが線形に増えます。つまり、イベント回数が100回なので、0.01ずつカウンタが増えます。イベントハンドラは、0,0.01,0.02,0.03,...,0.98,0.99,1のカウンタを受け取ります(後述するイベントハンドラの引数のvの値)。
addSubject()でイベントハンドラを渡します。振動させるためにsin()を使います。1周期の動きをさせるには、0から2πの値を取ればよいので、"v * 2*Math.PI"をsin()に渡します(カウンタvは0から1の間の値)。100は振幅です。高さ200pxを中心に振動させているので200を足して、最後にt.style.topに値をセットします。以下、このコードを改造していきます。
scriptaculousのコードを見ると、prototype.jsのmakePositioned()を使っています。t.style.position = 'absolute';を置き換えられそうなので、次のようにします(以下、この3行は省略)。
var t = $('target'); t.makePositioned(); t.style.top = '200px';
animator.jsのtransitionはいわばカウンタのgeneratorです。上の例のようにAnimator.tx.linearを使ってカウンタを線形にして、イベントハンドラのみを考えるのもひとつの手です。次のように、カウンタそのものの値の範囲を2πの単位で考えることもできます。
var anim = new Animator({duration: 4000, interval:40, transition: function(n){ return n * 2*Math.PI;}}); anim.addSubject(function (v) { var h = 200 + Math.round(100 * Math.sin(v)); t.style.top = h + 'px'; }); anim.play();
以下、Animator.tx.linearに話を戻します。
sin()に渡す数値の範囲を0から8πにすれば4往復します。更に、線形に1から0まで減少する数値をかけると、減衰する振動になります。コードは次のようになります。
var anim = new Animator({duration: 4000, interval:40, transition: Animator.tx.linear}); anim.addSubject(function (v) { var h = 200 + (1-v) * Math.round(100 * Math.sin(v * 8*Math.PI)); t.style.top = h + 'px';}); anim.play();
基本の動きはできました。微妙に気持ち悪いのがイベントハンドラのt(id="target"要素)への依存です。こういう場合、JavaScriptでは、次のようにクロージャを使うのが定石です。
var anim = new Animator({duration: 4000, interval:40, transition: Animator.tx.linear}); var makefn = function(elm, base) { return function(v) { var h = base + (1-v) * Math.round(100 * Math.sin(v * 8*Math.PI)); elm.style.top = h + 'px';} }; anim.addSubject(makefn(t, parseInt(t.style.top))); anim.play();
makefnは作ってすぐに使うだけなので、こういう場合、名前をつけずに呼ぶ方がJavaScript風です(以下のコード、単にmakefnを無くしただけです)。
var anim = new Animator({duration: 4000, interval:40, transition: Animator.tx.linear}); anim.addSubject((function(elm, base) { return function(v) { var h = base + (1-v) * Math.round(100 * Math.sin(v * 8*Math.PI)); elm.style.top = h + 'px';} })(t, parseInt(t.style.top))); anim.play();
振幅の100はハードコードのまま残っています。気持ち悪ければこれも引数にできます。
ここまで来ると、実は次のように1行にもできてしまいます。
(new Animator({duration: 4000, interval:40, transition: Animator.tx.linear})).addSubject((function(elm, base) { return function(v) { var h = base + (1-v) * Math.round(100 * Math.sin(v * 8*Math.PI)); elm.style.top = h + 'px';} })(t, parseInt(t.style.top))).play();
もっとも、これはやりすぎでしょう。可読性の観点からお勧めできません。
animator.jsは実はもっとすごいことができます。次のようなコードを書き足すと、背景色が徐々に変化します。
anim.addSubject(new CSSStyleSubject(t, "background-color:#ff0000", "background-color:#0000ff"));
- Category(s)
- カテゴリなし
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/inoue/animator-js-usage/tbping