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

parallax_eyecatch
1491件のシェア(殿堂入りの記事)

この記事は公開されてから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);
    }
  });
});

TransformはCSS3の機能なのでIE8等のレガシーブラウザでは動作しませんが、手軽に派手な動きを実現する事が出来ます。

CSSでパララックスエフェクト

ごくシンプルなモノですが、jQueryを一切使用せずにCSSのみでパララックスを実現することも可能です。

HTML

<body>
  <section id="first" class="content">
    <p class="logo">jQUery x HTML5 x CSS3</p>
    <article>
      <h1>Parallax sample.</h1>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, ....</p>
    </article>
  </section>

  <section id="second" class="content">
    <article>
      <h2 id="toc-only-css">Only CSS.</h2>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, ....</p>
    </article>
  </section>

  <section id="third" class="content">
    <article>
      <h2 id="toc-without-jquery">Without jQuery</h2>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, ....</p>
    </article>
    <img src="images/guernica.jpg" />
  </section>

  <section id="theend" class="content">
    <h2 id="toc-the-end">The End.</h2>
  </section>
</body>

CSS ※パララックスに関する部分のみ記述

.content {
  position: relative;
}
#first  { background: url(images/bg-parallaxsample01.jpg) 50% 0 no-repeat fixed; }
#second { background: url(images/bg-parallaxsample02.jpg) 50% 0 no-repeat fixed #000; }
#third  { background: url(images/bg-parallaxsample03.jpg) 50% 0 no-repeat fixed #000; }
#theend { background: url(images/bg-parallaxsample04.jpg) 50% 0 no-repeat fixed #e6cda4; }

/* section first */
.logo {
  position: fixed;
  top: 100px;
  left: 50px;
}
#first article {
  position: absolute;
  top: 200px;
  width: 800px;
}

/* section third */
#third article {
  position: absolute;
  top: 0;
}
#third img {
  position: absolute;
  left: 30px;
  top: 600px;
}

/* section the end */
#theend h2 {
  position: absolute;
}
CSS実装のポイント
- 各セクションの背景画像をbackground-position: fixed;で固定配置する
- テキストやイメージ画像などのコンテンツをposition: absolute;で絶対配置する

これにより、ページをスクロールしても背景画像は動かず、そのまま次のセクションに隠れるといった表現が実現できます。

jQuery x CSSでパララックスエフェクト

上記のCSSのみのサンプルに、jQueryを用いて更に動きを加えていきます。まずはjQueryでDOMを操作しやすくするために、HTMLの以下の箇所に追記します。

HTML

<section id="first" class="content">
  <p class="logo sprite" data-speed="-1.5" data-offsety="100">jQUery x HTML5 x CSS3</p>
  <article>
    <h1>Parallax sample.</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
  </article>
</section>

<section id="second" class="content">
  <article>
    <h2 id="toc-only-css1">Only CSS.</h2>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
  </article>
</section>

<section id="third" class="content">
  <article>
    <h2 id="toc-without-jquery1">Without jQuery</h2>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
  </article>
  <img src="images/img-parallaxsample01.jpg" class="sprite" data-speed="2" data-offsety="1600" />
</section>

<section id="theend" class="content">
  <h2 id="toc-the-end1" class="sprite" data-speed="0.8" data-offsety="4180">The End.</h2>
</section>

jQueryで動きをつける際のパラメータを、HTML5の機能である独自データ属性を使って指定します。

  • data-speed
  • data-offsety

独自データ属性とは、HTMLの名前空間に属さない属性のことで、コーダーが独自に定義する事ができます。jQuery Mobileを一度でも触った事のある方なら、その用途は理解できるかと思います。

よく知らないという方、より詳しく知りたいという方は、こちらのページをご参照ください。

次にJavaScriptの実装です。まずは背景画像がゆっくりと上に動いていく処理のみを実装します。

JavaScript

$(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ページは、一見すると非常に複雑な実装がされていると思いがちですが、ひとつひとつは今回挙げたサンプルコードの組み合わせであって、それが沢山積み重なっているだけのモノだったりします。※もちろん例外はあります。

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

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

参考サイト