iScroll を使ってスマートフォンで Parallax Scrolling #html5j

この記事は HTML5 Advent Calendar 2012 の18日目の記事です。

パララック・ススクロールとは?

2012 年の Web デザインで流行ったのは、「パララックス(視差)スクロール」(Parallax Scrolling)たったと思います。企業のイベントページなどで積極的に使われていました。パララックス・スクロールがどんなものかは文章で説明するよりも実際に見てもらえばすぐにわかるかと思います。

ただし、それは PC のサイトばかりで、スマートフォンではあまり無かったと思います。海外では Nike、日本では CA モバイルのページぐらいでしょうか。ちゃんと動くライブラリもなく、CA モバイルのページを手がけられた html5j.org 主宰の白石さんは 独自のライブラリを開発されてました。

なぜスマートフォンだと難しいのか?

パララックス・スクロールは、ページのスクロール量に応じて各部品のパラメータを変化させてアニメーションを実現するのですが、タッチデバイスの場合、指を離してから一定時間スクロールが継続する「慣性スクロール」の間、スクロール量を取得できるイベント(’onscroll’)が発行されず、その間、部品のパラメータを変化させることができません。

前述のサイトでは自前で慣性スクロールを実装し、その間のスクロール量を取得できるようにして、パララックス・スクロールを実現しています。

iScroll とは?

iScroll は、CSS の position: fixed; が使えないスマートフォンのためのライブラリで、ヘッダ/フッタを固定してスクロールできるようにします。このライブラリも、ブラウザが持つ慣性スクロールではなく、独自に慣性スクロールを実装しています。

仕事でスマートフォン向けページを制作する際に iScroll を使うことになりコードを見ていたら、慣性スクロール中にスクロールバーの描画をしており、そこで座標を取得できそうだったので、試してみたところ意外と簡単にできてしまいました。

iScroll の修正

iScroll からページのスクロール量(座標)を取得するために、独自のイベントを発行する処理を追加して座標を渡すようにしました。その処理で jQuery を使っているため、iscroll.js の読み込み前に jQuery を読み込んでおく必要があります。

次に座標の取得ですが、iScroll のソースコードの下記の箇所に、独自のイベントを発行する処理を追加します(iScroll v4.2.5 の 287行目〜312行目)。

iscroll/src/iscroll.js

_pos: function (x, y) {
  if (this.zoomed) return;

  x = this.hScroll ? x : 0;
  y = this.vScroll ? y : 0;

  if (this.options.useTransform) {
    this.scroller.style[transform] = 'translate(' + x + 'px,' + y + 'px) scale(' + this.scale + ')' + translateZ;
  } else {
    x = m.round(x);
    y = m.round(y);
    this.scroller.style.left = x + 'px';
    this.scroller.style.top = y + 'px';
  }

  // ================================================
  // send event 
  $(document).trigger('iscroll', {'x':x, 'y':-y});
  // ================================================

  this.x = x;
  this.y = y;

  this._scrollbarPos('h');
  this._scrollbarPos('v');
},

iScroll 側の修正は、304行目の1行を追加するだけです。

パララックス処理の実装

表現したい内容によって実装方法は異なってきますが、基本的にはページのスクロール量をもとに、各種パラメータを変更することになります。

作ったサンプルはこんな感じです。サンプルコードは GitHub で公開しています。(iPhone でしか確認していません。)

まず、先ほど iscroll.js に追加したイベントを、コンテンツ側のスクリプトで捕捉して座標を取得します。 iscroll/examples/parallax/script.js

$(document).bind('iscroll', function(e, pos){
  // pos.y にスクロール量が格納されているので、
  // その値を使って、各要素のパラメータを変更する。
});

取得した座標をもとに各要素の位置や色を変更しています。詳しくは、GitHub にアップしたサンプルコードをご覧ください。

最後に

世にあるパララックス・スクロール用のライブラリでは、もっと簡単に要素を制御できるような仕組みが提供されていますが、今回はそこまでたどり着けませんでした。ただ、スマートフォンでも Parallax Scrolling を実現できることと、基本的な考え方は示せたのかなと思います。参考になれば幸いです。

リンク