マウススクロールで1画面単位で上下にスライドする
発端はASUSのスマートフォンを紹介するサイトでした。
http://www.asus.com/jp/Phones/ZenFone_5_A500KL/
ZenFone 5のライティングページですが、マウスのスクロールボタンを回すとブラウザ全体を一気にスクロールして製品を紹介しています。この動きがちょっと格好良いなぁと思いまして。探せばおそらくはjQueryプラグインなどあるでしょうが、いつものごとく先ずは自分で試行錯誤してみます。
ただ、ASUSUのページはレスポンシブデザインではあるのですが、スマートフォン(タブレットでも)だとこの動きを封じて普通のスクロールになっています。また、キーボードの↑↓では反応しない、スクロールバーを移動しても途中で止まるようです。
これはこういう仕様というか、これが正解なのかもしれませんが、もう少し詰めてみたいと思います。
目指すもの
・ブラウザの縦・横のサイズに合わせてボックスを全画面にする
・キーボードの↑↓で反応させる
・ブラウザのスクロールバーでも反応させる
・タッチパネル対応機種にも対応させる
考え方
先ず、ロード時及びブラウザサイズ変更時に、指定したボックスの縦・横の幅をウインドのサイズに変更します。今回はボックス内のコンテンツは作成していませんが、jQueryなりEdge Animateなりで作成する事になると思います。
次に、スクロール量に関係なく1画面づつ自動でスクロールさせるのが目的なので、スクロールイベントに仕込むのが安易ですが妥当かと思います。スクロールが↑なのか↓なのか、これに応じて次のボックス(前のボックス)の上端をブラウザの上端まで移動させれば良いのでしょう。
とりあえずサンプル
動きは期待したものになっていますが、IEやChromeだとスクロール開始時に少しカクっとなります。Firefox(私はWaterFoxですが)だとスムーズ。
ボックスのHTMLとプラグインの設定
<div id="container" data-memory="1" data-mobile="" data-touch="" data-move=""> <div class="wrap" id="box1" style=" background: #0064FF">BOX 1</div> <div class="wrap" id="box2" style=" background: #008000">BOX 2</div> <div class="wrap" id="box3" style=" background: #ff7d27">BOX 3</div> <div class="wrap" id="box4" style=" background: #ee0101">BOX 4</div> <div class="wrap" id="box5" style=" background: #4D4D4D">BOX 5</div> </div> <script type="text/javascript"> jQuery(function(){ jQuery('.wrap').PresenSlide({ memory: '#container' //jquery dataを指定した場所 ,box: '#box' //ボックスのid名(数値抜) }); }); </script>
ボックスはwrapというclass名で、idの方はboxという文字に連番を振ります。それぞれ設定した名前をjQueryへ設定します。また、現在のボックス番号を記録したりするためにjQuery.dataを使いますので、今回はそれをcontainerに設定しました。これもプラグインの方へ設定します。
問題点など
先ず、スクロールイベントだとスマートフォンでは期待した動作をしてくれない事が解り、タッチイベントが発生した場合は、スクロール時の処理をキャンセルし、タッチイベントをトリガーとして処理しました。が・・・がっつりスワイプすると、どうしても1ページづつ移動してくれません。おそらく、スマートフォンブラウザはアドレスバーが見え隠れするので、そのあたりが問題なのかと思います。どうしても処理出来ず、これはここで断念。
パソコンの方ですが、これはスクロールした際に、scrollTop()から上下どちらにスクロールしたかは簡単に判断出来ます。なので、↓なら次の枠に移動すれば良いだけなのですが、スクロールイベントをトリガーとしている以上、1ピクセルでもスクロールすれば次の枠に移動しようとします。つまり、スクロールしている間じゅう、何度も繰り返し発生してしまい、一番↓まで一気に移動してしまいました。
これを回避するためカウントを設定し、スクロール時に加算→ボックスが移動を終える(animate.complete)とカウントを0に戻すようにし、カウントが1以上の場合は次のスライドを発生させないようにしまた。が・・・・completeじゃスライドを終えたというトリガーとは出来ず、setTimeoutで遅延させました。なので、スライドを終えて次のスライドが可能になるまで0.5秒ほどディレイが有ります。
とまぁ問題山積みなのですが、PCだけに限定し、プレゼンのように使うならまぁ使えるかなぁという事で、もし同じような事をされていてお悩みの方は参考までにソースをどうぞ。試行錯誤がモロ解りな酷いソースなのですが。
ASUSのソースは見てませんが、動きがスムーズですのでスクロールイベントじゃない何かで処理してるのかなぁと思います。