マウススクロールで1画面単位で上下にスライドする

2015-01-07

発端は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のソースは見てませんが、動きがスムーズですのでスクロールイベントじゃない何かで処理してるのかなぁと思います。