こんにちは。HTMLファイ部の岩淵です。

はじめに

皆さん、jQueryのanimateメソッドを使おうとしたときに、「ちょっとこれはanimateできないなぁ...」と困ったことはありませんか?

例えば、Google Maps API

setPosition(new google.maps.LatLng(lat, lng))

みたいな、変数をセットする関数を実行しなければいけないとき。

例えば、CSS3の

transform: translate(50px, 20px);

のように、transformの値を変化させるとき。

そんなときはjQueryのanimateを使わずにsetIntervalを使ったりして代用するところですが、 終了判定をしてclearIntervalを叩くのは面倒ですし、 animateを使うことによりcompleteで終了時の関数を実行したりイージングを付けられたりするので、animateがもたらす恩恵は大きいです。

そこでstep!!

そんな時、step関数が役に立ちます。 stepがどういうものかは、ちょうど去年のアドベントカレンダーで取り上げられていた記事を参考にしてください。

jQuery animateのStep関数を使ってみる | blog.makitasako.com

オブジェクトをanimateする

ところで、jQueryオブジェクトの対象はDOM要素だけだと思っていませんか? 実は任意のオブジェクトはjQueryオブジェクトにすることができます。

$({a: 5, b: 3, c; 8})

そして、オブジェクトのプロパティーに対して

var obj = {a: 5, b: 3, c: 8};
$(obj).animate({
  a: 7,
  b: 5,
  c: 10
}, {
  duration: 10000
});

のようにすれば、オブジェクトの各プロパティーを滑らかに変化させることができます。 実行中にobjの値をトレースしてみると、値が変動していることがわかると思います。

ちなみに、この例のように変化させるプロパティーが複数の場合、step関数がプロパティ毎に複数回実行されてしまうので、その場合はprogress関数を使った方がいいでしょう。

これを応用して、stepを使ったアニメーションを次のように書きます。

var object = {
  _t: 0
}

$(object).animate({_t: 1}, {
  duration: 1000,
  easing: 'linear',
  step: function(s) {
    setXY($('.box'), s*100, s*200);
  }
});

function setXY($elm, x, y) {
  $elm.css('transform', 'translate('+x+'px,'+y+'px)');
}

空のオブジェクトだとアニメーションしてくれないので、_tという0から1まで変化するプロパティーを持たせています。

このように、今までは黒魔術的にanimateさせる感じにしていましたが、 この度汎用的なstepアニメーションをjQueryプラグイン化しました。

それがこちらです! https://github.com/butchi/jquery.anim

<p class="elm">This is an example of jQuery.anim plug-in.</p>

このようなDOM要素に対して

var $elm = $('.elm');
$elm.anim({
  easing: 'easeOutBounce',
  step: function(t) {
    $(this).css({
      'transform' : 'scale(' + t + ')',
      '-o-transform' : 'scale(' + t + ')',
      'msTransform' : 'scale(' + t + ')',
      '-moz-transform' : 'scale(' + t + ')',
      '-webkit-transform' : 'scale(' + t + ')',
    });
  }
});

このように指定すればDOM要素をstepのアニメーションにすることができます。

ただし、アニメーションはキューに溜まらず、メソッドチェーンを使った逐次的アニメーションはできないのでそこら辺は改善の余地ありです。

皆さん、ぜひ使ってみてください!

stepまとめ:

  • フレーム毎に任意のコードを実行できる
  • 任意の関数を叩けるので、CSSプロパティー以外にも使える
  • CSS3のtransformプロパティーにも対応できる

明日は@Yuhiiskさんです。

HTML5飯