殿堂入り記事

HTML5 × CSS3 × jQueryを真面目に勉強 – #6 パララックスエフェクトの基本

2012.10.16

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

そんな訳で、パララックス・スクロールについて少し学んでみたので、超初心者向け(※自分含む)のサンプルをいくつか紹介していきたいと思います。

はじめに - パララックスエフェクトについて

パララックス(parallax)を直訳すると視差です。視差効果とは、視界が移動する際に各物体がそれぞれ異なったスピードでスクロールすることで、奥行き間をはじめとした視覚効果を指します。

アニメーションの世界ではディ○ニー映画で古くから使われていたり、ビデオゲームにおいても横スクロールアクションのゲームなどで昔から使われています。

JavaScript(jQuery)でパララックスエフェクト

1 | スクロール値を取得

どれだけスクロールしたかという値を取得します。これだけではまだパララックスも何もありませんが、全てはここから始まるのです。

$(function() {
  $(window).scroll(function() {
    var value = $(this).scrollTop();  //スクロール値を取得
    $('#scrollValue').text(value);
  });
});

スクロールすると、その値が画面右上に表示されます。

2 | Position値を変更して動きをつけてみる

取得したスクロール値を使って、矩形を動かしてみます。

$(function() {
  var top = $('#item1').offset().top; //y座標の初期値を取得
  $(window).scroll(function() {
    var value = $(this).scrollTop();  //スクロール値を取得
    $('#scrollValue').text(value);

    //取得したスクロール値を矩形のY座標値に指定
    //スクロール値を除算して移動距離に変化をつける
    $('#item1').css('top', top + value / 2);
    $('#item2').css('top', top + value / 4);
    $('#item3').css('top', top + value / 6);
    $('#item4').css('top', top + value / 8);
    $('#item5').css('top', top + value / 10);
  });
});

取得した値に計算処理を加えて、矩形の動きに変化をつけます。

3 | 矩形を横にも動かしてみる

topに加え、leftの値も変更してみます。要領は先ほどのサンプルと同じです。

$(function() {
  var top = $('#item1').offset().top; //y座標の初期値を取得
  var left1 = $('#item1').offset().left;  //item1のx座標の初期値
  var left2 = $('#item2').offset().left;  //item2のx座標の初期値
  var left3 = $('#item3').offset().left;  //item3のx座標の初期値
  var left4 = $('#item4').offset().left;  //item4のx座標の初期値
  var left5 = $('#item5').offset().left;  //item5のx座標の初期値

  $(window).scroll(function() {
    var value = $(this).scrollTop();  //スクロール値を取得
    $('#scrollValue').text(value);

    //取得したスクロール量を矩形のXY座標値に指定
    //スクロール値を除算して移動距離に変化をつける
    $('#item1').css({'top': top + value / 4});
    $('#item2').css({'top': top + value / 5, 'left': left2 + value / 8});
    $('#item3').css({'top': top + value / 6, 'left': left3 + value / 6});
    $('#item4').css({'top': top + value / 8, 'left': left4 + value / 5});
    $('#item5').css({'left': left5 + value / 4});
  });
});

4 | 背景画像を動かしてみる

コンテンツ領域の背景画像をスクロールで動かしてみます。

$(function() {
  var area2PosTop = $('#area2').offset().top;
  var area3PosTop = $('#area3').offset().top;
  var ashPosTop = $('#ashColorArea').offset().top;

  $(window).scroll(function() {
    var value = $(this).scrollTop();  //スクロール値を取得
    $('#scrollValue').text(value);

    // Area1
    $('#area1').css('background-position-y', value);

    // Area2
    if (value > area2PosTop) {
      $('#area2').css('background-position-y', value - area2PosTop);
      console.log('area2 variable');
    } else {
      $('#area2').css('background-position-y', 'top');
      console.log('area2 top');
     }

    // Area3
    if (value > area3PosTop) {
      $('#area3').css('background-position-y', (value - area3PosTop)*2);
      console.log('area3 variable');
    } else {
      $('#area3').css('background-position-y', 'top');
      console.log('area3 top');
    }

    // Area4
    if (value > ashPosTop) {
      var area4Top = value - ashPosTop - 800;
      $('#area4').css('background-position-y', area4Top);
    } else {
      $('#area4').css('background-position-y', -200);
    }

  });
});

Area1Area2は、画面の一番上までくるとそこで位置が固定されます。Area3は一番上まで来ると、今度は下に下がって行く動きをします。Area4は画面一番上まで上がらずに途中で位置が固定され、その上をRed color areaが通過するような動きをします。

5 | Transformさせてみる

スクロールによる縦横の動きだけでなく、CSS3のTransformプロパティも操作してみます。

$(function() {
  $(window).scroll(function() {
    var value = $(this).scrollTop();  //スクロール値を取得
    $('#scrollValue').text(value);

    var hoge1 = value * 0.001 + 0.5;
    if (hoge1 > 0.5) {
      $('#area1').css('transform', 'scale(' + hoge1 + ')');
    }

    if (hoge1 > 0.1) {
      $('#area2').css('transform', 'perspective(1000px) rotateY(' + value + 'deg)');
    }
    var hoge3 = 2 - value * 0.0009;
    $('#area3').css('transform', 'scale(' + hoge3 + ') rotate(' + value + 'deg)');

    var hoge4 = value * 0.0009;
    if (hoge4 <= 1) {
      $('#area4').css('opacity', hoge4);
    }
  });
});
[/javascript]
<ul>
  <li><a href="http://wakamsha.github.com/dev.cm/jhc-study/06/5-transform.html" target="_blank" rel="noopener noreferrer">View demo</a></li>
</ul>
<p>TransformはCSS3の機能なので<span class="bold cybercyan">IE8等のレガシーブラウザ</span>では動作しませんが、手軽に派手な動きを実現する事が出来ます。</p>


<h2 id="toc-css">CSSでパララックスエフェクト</h2>
<p>ごくシンプルなモノですが、jQueryを一切使用せずにCSSのみでパララックスを実現することも可能です。</p>
<p class="bold">HTML</p>


<p><span class="bold">CSS</span> <span class="ash small">※パララックスに関する部分のみ記述</span></p>

<dl>
  <dt>CSS実装のポイント</dt>
  <dd>- 各セクションの背景画像を<span class="bold">background-position: fixed;</span>で固定配置する</dd>
  <dd>- テキストやイメージ画像などのコンテンツを<span class="bold">position: absolute;</span>で絶対配置する</dd>
</dl>
<p>これにより、ページをスクロールしても背景画像は動かず、そのまま次のセクションに隠れるといった表現が実現できます。</p>

<ul>
  <li><a href="http://wakamsha.github.com/dev.cm/jhc-study/06/6-onlycss.html" target="_blank" rel="noopener noreferrer">View demo</a></li>
</ul>

<h2 id="toc-jquery-x-css">jQuery x CSSでパララックスエフェクト</h2>
<p>上記のCSSのみのサンプルに、jQueryを用いて更に動きを加えていきます。まずはjQueryでDOMを操作しやすくするために、HTMLの以下の箇所に追記します。</p>
<p class="bold">HTML</p>

<p>jQueryで動きをつける際のパラメータを、<span class="bold cybercyan">HTML5の機能である独自データ属性</span>を使って指定します。</p>
<ul>
  <li>data-speed</li>
  <li>data-offsety</li>
</ul>
<p>独自データ属性とは、HTMLの名前空間に属さない属性のことで、コーダーが独自に定義する事ができます。<a class="bold" href="http://jquerymobile.com/" target="_blank" rel="noopener noreferrer">jQuery Mobile</a>を一度でも触った事のある方なら、その用途は理解できるかと思います。</p>
<p>よく知らないという方、より詳しく知りたいという方は、<a href="http://www.html5.jp/tag/attributes/data.html" target="_blank" rel="noopener noreferrer">こちらのページ</a>をご参照ください。</p>
<p>次にJavaScriptの実装です。まずは<span class="bold">背景画像がゆっくりと上に動いていく処理</span>のみを実装します。</p>
<p class="bold">JavaScript</p>

$(function() {
  var $window = $(window);

  $('.content').each(function(index) {
    var $self = $(this);
    var offsetCoords = $self.offset();

    $(window).scroll(function() {
      // If this section is in view
      if (($window.scrollTop() + $window.height()) > offsetCoords.top && ((offsetCoords.top + $self.height()) > $window.scrollTop())) {
        var yPos = -($window.scrollTop() / 8);
        if ($self.attr('id') != 'first') {
          yPos += 126;
        }
        var coords = '50%' + yPos + 'px';
        $self.css('backgroundPosition', coords);
      }
    });
  });
});

ここまで実装できたら、一度ブラウザで確認してみます。スクロールしていくと各セクションの背景画像がゆっくりと上に動いているのが分かるかと思います。

次にスプライトの動きを実装します。以下のようにコードを追記します。

$(function() {
  var $window = $(window);

  $('.content').each(function(index) {
    var $self = $(this);
    var offsetCoords = $self.offset();

    $(window).scroll(function() {
      // If this section is in view
      if (($window.scrollTop() + $window.height()) > offsetCoords.top && ((offsetCoords.top + $self.height()) > $window.scrollTop())) {
        var yPos = -($window.scrollTop() / 8);
        if ($self.attr('id') != 'first') {
          yPos += 126;
        }
        var coords = '50%' + yPos + 'px';
        $self.css('backgroundPosition', coords);

        // Check for other sprites in this section
        $('.sprite', $self).each(function(index) {
          var $sprite = $(this);
          var yPos = -($window.scrollTop() / $sprite.data('speed')) + $sprite.data('offsety');
          $sprite.css('top', yPos);
        });
      }
    });
  });
});

HTML側で指定したデータ属性の値は、以下のようにしてJavaScript側から参照する事が出来ます。

<p class="logo sprite" data-speed="-1.5" data-offsety="100">jQUery x HTML5 x CSS3</p>
$('.logo').data('speed'); // -1.5

おわりに

一昔前と違って、今ではフリーランスのWebデザイナーのポートフォリオ等だけでなく、企業のホームページや、気の利いたスマートフォンアプリのランディングページなどにもパララックスエフェクトが取り入れられているのを良く見かけます。それらの素晴らしくハイクオリティなWebページは、一見すると非常に複雑な実装がされていると思いがちですが、ひとつひとつは今回挙げたサンプルコードの組み合わせであって、それが沢山積み重なっているだけのモノだったりします。※もちろん例外はあります。

なので焦らず時間を掛けて一つずつ組み込んでいけば、ド派手なパララックスエフェクトを作り上げることも、そこまで難しいモノではありません。

実際に学習で作るうえでも、見た目が華やかな効果のモノはモチベーションの維持に一役買いますし、スクロールによる座標取得といったプログラミングは他の開発においても必ず役に立ちますので、この類が苦手という方は是非ともしっかりと身に着けておきたいものです。

参考サイト