読んで覚える、触って体験!JavaScript&CSS3~gihyo.jp×jsdo.it presents

第4回jQueryでアニメーション(お題編)

はじめに

jQueryの機能を大きく分けると、DOM操作、アニメーション、イベント処理、Ajax、その他のユーティリティ関数といった分類ができます。DOM操作は前回の記事で解説したような、HTMLの要素を追加したり書き換えたりといった操作です。今回はその中の1つ、アニメーションについて解説します。アニメーションも正確にはDOM操作に分類されますが、アニメーションだけでかなり大きな比重を占めるので今回は通常のDOM操作とわけて考えます。イベント処理やAjax、ユーティリティ関数についても連載の後のほうで解説する予定です。

JavaScriptでアニメーションの基本

まず始めに、jQueryを使わないでアニメーションをする方法を紹介します。jQueryのアニメーションが実際に内部でどのような処理が行われているかを知ることでその後の理解度が増すと思います。JavaScriptでアニメーションは基本的にはCSSの値をミリ秒単位で変更することによって実現します。たとえば以下の例では、JavaScriptでCSSのtopの値を高速に変更することによりアニメーションを実現しています。

// topの初期値を設定
var top = 0;

// タイマー処理。1ms置きに実行
var timer = setInterval(function() {
  // topの値を10増やす
  top += 10;

  // topの値を適用する
  box.style.top = top + 'px';

  // topの値が300以上になったらタイマーをクリアする
  if (top > 300) {
    clearInterval(timer);
  }
}, 1);

ここではsetIntervalというJavaScriptのタイマー機能を使っています。このタイマー機能で1ミリ秒単位でtopの値を変更しています。実際には以下のように動きます。

JavaScriptでのアニメーション - jsdo.it - share JavaScript, HTML5 and CSS

これがJavaScriptでのアニメーションの基本になります。しかし実際には上記のような処理だと、ブラウザの処理が追いつかず期待した動作をしなかったり、複雑なアニメーションを記述するのがとても大変だったりします。jQueryの内部でも同じくタイマー機能を使った処理でアニメーションが行われていますが、それを意識せず直感的に書けるようになるのがjQueryのアニメーションの特徴です。

JavaScriptでのアニメーションに関して、詳しくは以下の記事に書いてあるので参考にしてみてください。

これでできる! クロスブラウザJavaScript入門 第17回 アニメーションの基礎
http://gihyo.jp/dev/serial/01/crossbrowser-javascript/0017

jQueryのanimateを使ったアニメーションの基本

jQueryでアニメーションする場合はanimateという関数を使います。animteは以下のように記述します。

.animete(アニメーションする属性, アニメーションの速度, 変化量, 終了時の処理)

必須なのはアニメーションする属性だけで、後はオプションなので指定しなくても動作します。一番簡単な例では以下のようになります。

$('#box').animate({ top: 300 });

これだけで先ほどのものとほぼ同じような動きになります。

jQueryでのアニメーション - jsdo.it - share JavaScript, HTML5 and CSS

また、複数の属性を指定することも可能です。

$('#box').animte({
    top: 300,
    width: 300
});

こうすると以下のようにtopとwidthの値を同時に変更したアニメーションを実装することが可能です。

アニメーションする属性の複数指定 - jsdo.it - share JavaScript, HTML5 and CSS

もしくは以下のように指定できます。

.animate(アニメーションする属性, オプション)

属性のところは同じですが、速度や変化量などは全てオプションのところで指定できます。またqueueやstepなどこの記述じゃないと指定できないものもあります。

アニメーションの速度

次に第二引数で指定するアニメーションの速度について解説します。第二引数に指定できるのはアニメーションが始まってから終わるまでの秒数(ms)を指定します。

$('#box').animate({ top: 300 }, 1000);

このように指定すると、アニメーションを1000ms(1秒)かけて実行します。完了までの時間なのでここに指定する数字が小さいほど高速でアニメーションするということになります。また、数字だけでなく、slow、fastという文字列を指定できます。これらはそれぞれ、slowが600、fastが200という数字を指定したのと同じことになります。速度を指定しなかった場合のデフォルトは400です。

以下の例では自由にアニメーションの速度を指定できるようにしていますので試してみてください。

アニメーション速度 - jsdo.it - share JavaScript, HTML5 and CSS

変化量

第三引数では変化量を指定します。変化量というのはイージング(easing)と呼ばれるもので、アニメーションがずっと同じ速度で変化するのか、はじめはゆっくりで最後は早く変化するのかといったものを指定するものです。jQueryのanimateで指定できるのはlinearとswingという2つで、デフォルトはswingです。もちろん自分で独自のイージングを設定することも可能ですし、jQuery Easingというプラグインを使えば多数のイージングを使うことが可能です。なお、jQuery Easingはjsdo.itで利用できるライブラリに含まれているので簡単に利用可能です。さまざまなイージングを以下で確認できます。

様々なeasing - jsdo.it - share JavaScript, HTML5 and CSS

アニメーション終了後の処理

アニメーションは非同期で動作します。非同期で動作するというのは、終了を待たずに次の処理へ進むということになります。たとえばアニメーションの実行が終わったあとにアラートを出したいという場合に以下のようなコードを書いても期待通りに実行されません。

$('#box').animate({ top: 300 });
alert('animate complete!');

このコードは以下のようになります。

アニメーション終了後の処理(失敗⁠⁠ - jsdo.it - share JavaScript, HTML5 and CSS

なぜアニメーションが非同期で実行されるのかというと、アニメーションが1分かかる場合、終了を待っていると1分間何も実行されないことになるので、そのようなことがないようにアニメーションなどの処理は通常、他の処理と平行して動作するのです。しかし終了を待たないということは終了後の処理を記述したいときに困ったことになります。そこでコールバックという仕組みで、アニメーション終了後の処理をあらかじめ登録しておいて、終わったら実行するようにします。

$('#box').animate({ top: 300 }, null, null, function() {
    alert('animate complete!');
});

これで期待した動作になります。

アニメーション終了後の処理 - jsdo.it - share JavaScript, HTML5 and CSS

jQuery組み込みのアニメーション

jQueryのアニメーションはこれまで紹介してきたanimate関数を使えば簡単なアニメーションから複雑なアニメーションまで実装することが可能ですが、よく使うフェードアウトやスライドダウンなどのアニメーションはショートカットが用意されています。

// スライドダウン
$('#box').slideDown();

// スライドアップ
$('#box').slideUp();

// スライドダウン/アップの切り替え
$('#box').slideToggle();

// フェードイン
$('#box').fadeIn();

// フェードアウト
$('#box').fadeOut();

// フェードイン/アウトの切り替え
$('#box').fadeToggle();

これらのショートカット関数にも、animateと同じく、速度、変化量、終了後の処理を指定することができます。

$('#box').sldeDown('fast', 'linear', function() { ... });

もっと高度なアニメーション

アニメーションしている要素の取得

jQueryでは以下のような記述で現在アニメーション中の要素を取得できます。

$(':animated')

これにより、アニメーション中の要素にだけ何か処理をするといったことも簡単に記述可能です。以下の例ではアニメーション中の要素だけ色を変更をするという処理を実装しています。アニメーション前やアニメーション終了後には実行されないのがわかると思います。

アニメーション時のセレクタ - jsdo.it - share JavaScript, HTML5 and CSS

アニメーションの停止

アニメーションを実行したときに前回のアニメーションが終わってない場合、前回のアニメーションが終わるまで次のアニメーションはキュー呼ばれるものに溜められ、それまでのアニメーションが全て実行されるまで待ちます。

たとえばボタンを押したときにアニメーションを実行するという処理を実装する際に、ボタンを連打すると予期しない動作になることがあります。これを防ぐためには、アニメーションを行うときには前回のアニメーションを停止しておく必要があります。jQueryのアニメーションを止めるには以下のように記述します。

$('#box').stop();

これまで提示していた例ではすべてこの処理を入れているので参考にしてみてください。

連続したアニメーション

jQueryのアニメーションはただつなげて書くだけで簡単に連続したアニメーションを定義できます。以下のように書くと、topが300になった後0に戻すという処理になります。

$('#box').animate({ top: 300 }).animate({ top: 0 });

これも上記で説明したキューというものに溜めて順次処理するためにこのような記述が可能になっています。また、delayという関数を使えば次のアニメーションに移るまでの待ち時間を指定することも可能です。

$('#box')
    .animate({ top: 300 })
    .delay(1000)
    .animate({ top: 0 });

このように記述するとアニメーションの途中で1秒間待ってから再度アニメーションを開始します。

連続したアニメーション - jsdo.it - share JavaScript, HTML5 and CSS

並列なアニメーション

連続したアニメーションではなく、同時にアニメーションしたい場合もあるでしょう。同時にアニメーションする場合、前述したプロパティの複数指定でも可能ですが、その場合は速度などをそれぞれのアニメーションに指定するということができません。その場合は以下のように記述します。

$('#box')
  .animate({ top: 300 }, {
    duration: 2000,
    queue: false
  })
  .animate({ left: 300 }, {
    duration: 1000
  });

queueというのがキューに溜めるかどうかの指定で、これをfalseにするとキューに溜めずにすぐに次のアニメーションに移行します。durationというのはアニメーションの速度です。これでそれぞれのアニメーションは違う速度で並列に実行されます。

並列なアニメーション - jsdo.it - share JavaScript, HTML5 and CSS

stepを使って処理毎に関数を実行する

stepにコールバック関数を設定することにより、アニメーション中に値が書き換わるごとに登録した関数を実行することができます。この関数が呼ばれるのは値が書き換わったときなので、設定した速度やイージングなどによっていつ、何回呼ばれるかは変わってきます。stepは以下のように記述します。

$('#box').animate({ top: 300 }, {
  duration: 2000,
  step: function(now) {
    $now.text( now + 'px' );
  }
});

これで今topの値がいくつなのかを画面に表示することができます。

アニメーションの処理毎に関数を実行する - jsdo.it - share JavaScript, HTML5 and CSS

プロパティごとにイージングを設定する

animateでは複数のプロパティを同時に指定できますが、それらに対してそれぞれで異なるイージングを指定することが可能です。これにより複雑なアニメーションが可能になります。以下のように指定します。

$('#box').animate({
  top: [300, 'easeOutBounce'],
  left: [300, 'linear']
}, 1000);

もしくは以下のように書いても同じです。

$('#box').animate({
  top: 300,
  left: 300
}, {
  duration: 1000,
  specialEasing: {
    top: 'easeOutBounce',
    left: 'linear'
  }
});

これは以下のように動作します。

属性毎にeasingを設定する - jsdo.it - share JavaScript, HTML5 and CSS

今回のお題

今回のお題はタブ切り替えのコンテンツにアニメーションを追加してリッチなUIにするというものです。以下のような単純にshowとhideで切り替えるだけのものを作成したのでこれのタブ切り替えをかっこいいアニメーションで切り替わるようにしてください。

jQueryアニメーションのお題 - jsdo.it - share JavaScript, HTML5 and CSS

fadeIn、fadeOutなどの簡単なものでもいいですし、animateやイージングを駆使しての独自のアニメーションにも挑戦してみてください。

おすすめ記事

記事・ニュース一覧