パララックスで背景を動かしてみよう

javascript

前回、「パララックス効果をCSSのみで実装してみよう(固定)」いうのをやってみました。今回はその背景画像がスクロールするとゆっくり上に移動するものを作ってみようかと思います。 ライブラリを使ってもいいのですが作り方を知るという意味で実際にコードを組んでみます。

今回のパララックスの流れ

実際にどのような感じになるのか。ポイントとしては下記になるのかなと。

  • 大枠は前回作成した背景の設置と同じ方法
  • スクロールしたら、background-position-yで縦方向に移動させる
  • ウィンドウの高さ以上で隠れてる場合は、スクロールで上がってきてウィンドウの領域に入ったらスクロールさせるようにする

See the Pen 背景画像をパララックスする方法(ずらし効果あり) by kiriyama (@kirikirimai) on CodePen.

最終的には上記のようになる感じです。

各ソースコードの説明

余計なコードとhtmlは前回と同じなので、説明は省きます。

HTML

ここはコンテンツ1

ここはコンテンツ2

ここはコンテンツ3

CSS

.parallax {
    background-attachment: fixed;
    width: 100%;
    padding-top: 66.66%;
    background-position: center 0;
    background-size: cover;
    background-repeat: no-repeat;
  }

CSSは前回と少しだけ変更があります。高さを確保するために「padding-top」で高さを出しています。高さの算出方法は「表示画像の高さ ÷ 表示画像の幅 × 100」で計算すると「66.66%」としています。

そして「background-position」ですが横方向(x軸)はcenterにしていますが、縦方向(y軸)は「0」にしてください。縦方向に移動させるのでcenterにすると急にカクっとなります。

jQuery

$(function () {
  
  //各背景画像のtopの位置を取得
  var bg1_top = $(".bg_1").offset().top;
  var bg2_top = $(".bg_2").offset().top;
  var bg3_top = $(".bg_3").offset().top;
 
 // ウィンドウの高さを取得
  var win_h = $(window).height();
 
 //各背景画像を動かすタイミングの位置を計算
  var start_bg1 = bg1_top - win_h;
  var start_bg2 = bg2_top - win_h;
  var start_bg3 = bg3_top - win_h;
  

  $(window).scroll(function () {
    
    //スクロール量
  var y = $(this).scrollTop();
   
  //スクロール量と動かすタイミング位置を判定した場合は背景画像を動かす
    if (y >= start_bg1) {
      $('.bg_1').css('background-position-y', -(y - bg1_top) * 0.2 + 'px');
    } 
    if (y > start_bg2) {
      $('.bg_2').css('background-position-y', -(y - bg2_top) * 0.2 + 'px');
    }
    if (y > start_bg3) {
      $('.bg_3').css('background-position-y', -(y - bg3_top) * 0.2 + 'px');
    }
  });
});

サンプルだとスクロール量などを出力してますが、簡潔にするために出力する箇所は省いてます。

まず、重要はポイントですが、スクロールの際にウィンドウの範囲外の背景画像の要素は動かさないというのがポイントになります。
なぜならスクロールしてすべての背景画像を動かすとウィンドウの範囲に入ってきた時にはすでに背景が動いてしまってるので、中途半端な位置まで背景画像が移動しているからです。

ではどうしたらいいのか?それは、各背景画像はウィンドウの範囲内に入った瞬間を検知すればいいので、各背景画像の位置からウィンドウの高さ分を差し引いた値とスクロール量を調べればいいのです。下記の画像を参考にしてください。

それが下記のコードの部分です。サンプルの動作を確認していただくと分かりますが、「スクロール量」と「2番・3番目の背景画像が動く位置」を見るとウィンドウ画面入ってきた際に「動いた」と変わると思いますが同じ数値に近いことが分かるかと思います。

 //各背景画像を動かすタイミングの位置を計算
  var start_bg1 = bg1_top - win_h;
  var start_bg2 = bg2_top - win_h;
  var start_bg3 = bg3_top - win_h;

後はscrollイベント内でスクロール量をチェックして上記で割り出した値より上回れば、ウィンドウ画面内に入ったと判定できるので、背景画像の「background-position-y」のプロパティを「-(マイナス)」方向に移動させれば完成です。
その際のですが、スクロールと同じスピードだと速すぎるので「*0.2」などの数値を掛け算することでスピードをゆっくりにしてあげる事で全面のコンテンツと背景画像のスピード差が生まれパララックス効果が引き立つと思います。

まとめ

ざっと説明してきましたが、「 background-attachment :fixed」を使用してるせいかサンプルだとスマホで見るとか画像が大きくて何が何だかわからないという感じになってるのでスマホの場合は画像を変えるなどしたほうがいいかもですが。 

Codepenではないサンプルもリンク張っておきます。
DEMO