パララックスでのイベントの考察。scroll / throttle / debounce / touchmove / mousewheel
.[追記:2015/05] 2012年12月の投稿なので情報がかなり古いです。iOS7ではスクロールイベントが取りやすくなってます。とはいえ、スマホのパララックスは要注意。
こんにちは。Advent Calendar 2012 軽めのjQuery の17日目を担当します。
http://www.adventar.org/calendars/29
パララックスエフェクトを実装するためのイベントについて少し触れてみたいと思います。
パララックスエフェクトで考えること
パララックスエフェクトのような動きを考える時、いくつかの項目を考慮する必要があるとおもうんですが、例えば
- イベント発火のタイミング
- パララックスエフェクトの実装
- スマホで動作する際の妥協点。
- 如何に心地よくぬるぬると動かせれるか。
などなど。僕の場合このあたりを考えるんですけど、一番最後の、如何に心地よくぬるぬると動かせれるかが、パララックスのエフェクトを実装するなかでの決め手だと思っています。
実際の所写真などを多用すると、どうしても重くなりますし、いろいろ試行錯誤してみて、ある程度のところで妥協点を見つけるという感じになってしまいますが。
軽めのjQueryということで、イベントの発火のタイミングの一部と、心地よくアニメーションする方法の一部を急いで作ったDemoを見ていただきながら少し考えてみたいと思います。すこし重くなるかもしれません。
ここで使用しているDemoファイルは、githubにも置いておきましたので、ご自由にお使いください。
イベントについて
PCではscrollイベントで十分なんですけど、スマホだと、全然気持ちよくない。
これは、touchmoveイベントを使って解決します。ある程度。
あと、ちょうど今回のAdvent calendarの13日目 ELAB.さんも取り上げられていらっしゃいましたが、throttle/debounceという、いい具合にイベント実行回数を間引くプラグインがあり、これを使えば多少重たいのが軽減できそうな気がします。
気持よく動かすってことについては、簡単に実装することを考えると、jQuery Animationを使うことになるのかなと。
もっと気持ち良さを求めるなら、別のアニメーション方法を考える必要があって、それこそ、Nikeエアジョーダン2012のような鉄板サイトのコードリーディングされることがベストだと思います。
scroll / throttle / debounce / touchmove / mousewheelイベントの比較
それでは本題、parallaxのデモファイルと一緒に見ていきたと思います。この記事ではデモファイルを3つ用意しました。
- アニメーション無しで、CSSプロパティを変更
- jQueryアニメーションを利用して、CSSプロパティを変更
- 1,2のスマホイベントのみピックアップ
それぞれPCとスマホの両方で見ていただきたいなと。PCでとスマホと挙動が全然違うので。
比較したのは以下のイベントの組み合わせ7パターン
// パターン1:基本のscrollイベント $(document).on("scroll", function(){ /* 処理 */ }); // パターン2:mousewheelプラグイン利用 $(document).on("mousewheel", function(){ /* 処理 */ }); // パターン3:throttleプラグイン利用 $(document).on("scroll", $.throttle( 250, function(){ /* 処理 */ }) ); // パターン4:throttleプラグイン利用(debounce) $(document).on("scroll", $.debounce( 250, function(){ /* 処理 */ }) ); // パターン5:touchmoveイベント。スマホ用のスクロールイベント $(document).on("touchmove", function(){ /* 処理 */ }); // パターン6:touchmove と throttleプラグインの連携 $(document).on("touchmove", $.throttle( 250, function(){ /* 処理 */ }) ); // パターン7:touchmove と throttleプラグイン(debounce)の連携 $(document).on("touchmove", $.debounce( 250, function(){ /* 処理 */ }) );
1.アニメーション無し。CSSプロパティ変更
1つめは、アニメーションせず、スクロールに応じてcssプロパティをいじってしまう方法です。
各イベントの比較です。
// こんな感じでパララックスぽいアニメのテスト $("#id").css({top: /* 数値 */ });
これからわかることは、
- PC:scrollが一番きれい。throttleとdebounceだと、アニメーションをいれないとひどい。
- スマホ:scrollイベントはスクロール終了時に一度実行されるだけ。
かわりに、touchmoveイベントを使う。
cssの設定によっては、移動時にチカチカする。(demoではpositionのtopをずらしている)
2.jQueryアニメーション利用。
2つめは、jQuery Animationでいじる方法、それぞれのイベントの比較。
// こんな感じでパララックスぽいアニメのテスト $("#id").animete({top: /* 数値 */ },10000);
これからわかることは、
- PC:throttleイベントがうまい具合に間引いてくれて、スクロール中にも比較的なめらかなアニメーションになるし、イベント発火回数も少ない。debounceはスクロールイベント終了時にしか実行されないので、もたつく。
- スマホ:どれも似たような感じ。jQueryアニメーション実行前にstop()をいれてるので、結局スクロール途中のアニメーションは間引かれてしまうような挙動になる。
だとしたらscroll & throttleイベントを利用するのが一番かしこい選択?
3.スマホでの挙動を比較
3つめは、スマホ用のTouchmove eventの比較です。
Demo1とDemo2の、それぞれtouchmoveイベント類だけをまとめた、3+3の6種の比較です。
当然ですが、PCでは動きません。
- スマホで見た場合:アニメーションをいれたほう(右側3つ)はどれも無難です。
- もしスクロール時のチカチカpositionがかわってしまうのを解消できたら、throttleとdebounceを使わず、touchmoveだけが一番きれいだとおもいます。
何がベストか。
デモで少しイメージをつかめたでしょうか。
- PC:scrollもしくは、throttle。
- スマホ:アニメーションを入れるべきで、イベントはどれもにたような感じ。throttleを使うのがよいかな。
ただ言えることは、コンテンツの内容によってパフォーマンスが随分かわってくるでしょうから、結局のところ自分で試行錯誤するしかない。
また、気持ちよさを求めるなら、間違いなくAirJordan2012をコードリーディングすべきですよね。
なお、あまり目立ちませんでしたが、mousewheelプラグインだと上スクロール/下スクロールを検知することができます。ここで紹介しているmousewheel以外のイベントでは、その実装が面倒なのでmousewheelが活躍することが結構あると思います。(今回のDemoではスマホでmousewheelが発火してないですが、確か動かせたような記憶があったりなかったり。。。忘れてしまいました。)
以上です。重くはないですけど軽めのjQueryではなくなっちゃいましたが、少しでも参考になれば幸いです。
また、自分もまだまだ検証中なので、手軽でもっとスマートなやり方があるよってご存知のかたいらっしゃいましたら、コメント欄からでもぜひご教授いただきたいです。
githubにこれらのDEMOファイルを置いておきましたので、ご自由にお使いください。
では次の方にパス。