jquery 背景画像を使ったパララックス

2013年12月28日

背景画像を使ったパララックスに関するメモ。

参考にさせていただいたサイト:
HTML5 × CSS3 × jQueryを真面目に勉強 – #6 パララックスエフェクトの基本

CSSを使ったパララックス

jQuery を使用しないで CSS で単純なパララックス(背景画像を固定して表示)を実現する方法。

  • 各 div 要素(#first, #second, #third, #end)に背景画像(960 x 800)を用意
  • 「background-attachment プロパティ」の値を「fixed」に指定(背景画像はブラウザの表示領域に対して固定される)
  • 「background-position プロパティ」の水平位置の値を「50%」または「center」に指定
  • 「background-position プロパティ」の垂直位置の値を「0(0%)」または「top」に指定(値の指定が1つだけの場合、水平位置のみに適用され、垂直位置は50%と解釈される)

サンプル

HTML

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>CSS Parallax</title>
</head>
<body>
<div id="wrapper">
<div id="first" class="content">
    <p class="title">CSS Parallax</p>
    <div class="inner">
      <h1>1. Lorem ipsum dolor</h1>
      <p>Ducimus, deleniti, minus minima delectus beatae... </p>
    </div>
  </div>
 
  <div id="second" class="content">
    <div class="inner">
      <h2>2. Facilis, molestias</h2>
      <p>laboriosam, asperiores quisquam recusandae ipsum  ...</p>
    </div>
  </div>
 
  <div id="third" class="content">
    <div class="inner">
      <h2>3. Quod, illum fuga</h2>
      <p>Laudantium, accusamus, sit, adipisci animi quae... </p>
    </div>
    <img src="images/pallarax1/picture01.jpg" alt=""/>
  </div>
 
  <div id="end" class="content">
    <h2>The End.</h2>
  </div>
</div>
</body>
</html>

CSS

  • 背景画像を background-position: fixed; で固定配置し、ポジションを「50% 0」に指定
  • テキストやイメージ画像などのコンテンツを position: absolute; で絶対配置
  • #first の <p class=”title”> は固定配置(fixed)。z-index を指定すれば常に表示できる。
body {
  margin: 0;
  padding: 0;
  line-height: 1.5;
  font-size: 16px;
}
#wrapper {
  position: relative;
  width: 960px;
  height: 3500px;
  margin: 0 auto;
  padding: 0;
}
  
.content {
  position: relative;
  margin: 0 auto;
  padding: 0;
  height: 800px;
}
#first  { 
  background: url(images/pallarax1/div1_bg.jpg) 50% 0 no-repeat fixed;   
}
#second { 
  background: url(images/pallarax1/div2_bg.jpg) 50% 0 no-repeat fixed #000;
}
#third  { 
  background: url(images/pallarax1/div3_bg.jpg) 50% 0 no-repeat fixed #000;
}
#end { 
  background: url(images/pallarax1/div4_bg.jpg) 50% 0 no-repeat fixed #FFF ;
}
 
/* div#first */
.title {
  position: fixed;
  /*z-index: 10;*/
}
#first .inner {
  position: absolute;
  top: 200px;
  left: 20px;
  width: 400px;
}
/*  div#second  */

#second .inner {
  position: absolute;
  top: 80px;
  left: 100px;
  padding: 10px 20px;
  width: 445px; 
}
 
/* #third .inner  */
#third .inner {
  position: absolute;
  top: 0;
  padding: 10px 20px;
  color: white;
}

#third img {
  position: absolute;
  left: 30px;
  top: 500px;
}
 
/* div#end */
#end h2 {
  position: absolute;
  color: white;
  font-size: 4em;
  left: 50%;
  top: 180px;
  width: 300px; 
}

fixed を使わず jQuery を使う場合

背景画像の CSS で fixed を使わず jQuery を使って同じことをするには以下のようにできる。

サンプル

HTML は同じ。

CSS では背景画像の指定で「fixed」を削除(ポジションは削除してもそのままでも同じ。 jQueryで変更)

CSS の変更箇所

#first  { 
  background: url(images/div1_bg.jpg) no-repeat ;   
}
#second { 
  background: url(images/div2_bg.jpg) no-repeat  #000;
}
#third  { 
  background: url(images/div3_bg.jpg) no-repeat  #000;
}
#end { 
  background: url(images/div4_bg.jpg) no-repeat  #FFF ;
}

jQuery ではそれぞれの div 要素(.content)について、それらがブラウザに表示されている場合に background-position を調整。

ブラウザに表示されているかの判定

  • ブラウザの下辺の位置の値「$window.scrollTop() + $window.height()」がその領域の上辺の位置の値「offsetPositions.top」より大きく
  • かつその領域の下辺の位置の値「offsetPositions.top + $self.height()」がブラウザの上辺の位置の値「$window.scrollTop()」より大きい場合

その領域の垂直位置の値を、その時点のスクロール量「$window.scrollTop()」からその領域のオフセットを引いたものに指定。

jQuery

<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
jQuery(function($){
  var $window = $(window);
 
  $('.content').each(function(index) {
    var $self = $(this);
    var offsetPositions = $self.offset();
 
    $(window).scroll(function() {
      //この領域がブラウザに表示されている場合
      if (($window.scrollTop() + $window.height()) > offsetPositions.top && ((offsetPositions.top + $self.height()) > $window.scrollTop())) {
        var offsetY = $window.scrollTop() - offsetPositions.top ;
        var positions = '50%' + offsetY + 'px';
        $self.css('backgroundPosition', positions);
        //console.log(index + ' offsetY : ' + offsetY + '    $window.scrollTop: ' + $window.scrollTop());
      }
    });
  });

});
</script>

または、以下のようにすると似たようなことが可能。但し表示される重なり順が異なる。

サンプル

jQuery(function($){ 
  var first$ = $('#first');
  var first_ot = first$.offset().top;  
  var second$ = $('#second');
  var second_ot = second$.offset().top;  
  var third$ = $('#third');
  var third_ot = third$.offset().top;  
  var end$ = $('#end');
  var end_ot = end$.offset().top;
  
  $(window).scroll(function(){
    var dy = $(this).scrollTop();
     
    if(dy > first_ot) {
      first$.css('background-position',  '0 ' + (dy-first_ot) + 'px');        
    }else{
      first$.css('background-position', '0 0');
    }
    
    if(dy > second_ot) {
      second$.css('background-position', '0 ' + (dy-second_ot)  + 'px');      
    }else{
      second$.css('background-position', '0 0');
    }
    
    if(dy > third_ot) {
      third$.css('background-position', '0 ' + (dy-third_ot)  + 'px');
    }else{
      third$.css('background-position', '0 0');
    }
    
    if(dy > end_ot) {
      end$.css('background-position', '0 ' + (dy - end_ot)  + 'px');
    }else{
      end$.css('background-position', '0 bottom');
    }  
  });
});

CSS と jQuery でパララックス

背景画像がゆっくりと上に動いていくように見えるようにする。

サンプル

HTML は同じ。
CSS は 背景画像に fixed を指定。

CSS

#first  { 
  background: url(images/div1_bg.jpg) center 0% no-repeat fixed;   
}
#second { 
  background: url(images/div2_bg.jpg) center 0% no-repeat fixed;
}
#third  { 
  background: url(images/div3_bg.jpg) center 0 no-repeat fixed;
}
#end { 
  background: url(images/div4_bg.jpg) center 0 no-repeat fixed;
}
  • jQuery では、垂直方向のポジションをスクロール量によって変化するように指定
  • CSS で背景画像に fixed を指定しているので下記の「offsetY」の値は、ブラウザの表示領域のトップからの量
  • 全ての領域で同じような速度にするには以下のように offsetPositions.top の値を差し引く
  • offsetPositions.top の値を差し引かない場合は下の領域に行くほどスクロール量が増えるので速度もさらに変化するので、画像のサイズなども考慮する必要あり
  • 「17」は適当な値(速度を決めるために利用する値)
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
jQuery(function($){
  var $window = $(window);
 
  $('.content').each(function(index) {
    var $self = $(this);
    var offsetPositions = $self.offset();
 
    $(window).scroll(function() {
      // この領域がブラウザに表示されている場合
      if (($window.scrollTop() + $window.height()) > offsetPositions.top && ((offsetPositions.top + $self.height()) > $window.scrollTop())) {
        var offsetY =  -(($window.scrollTop() - offsetPositions.top)/ 17); 
        //var offsetY =  -($window.scrollTop()/ 17); 
        var positions = '50%' + offsetY + 'px';
        $self.css('backgroundPosition', positions);
      }
    });
  });
});
</script>

fixed を使わない場合

背景画像の CSS で fixed を使わない場合は以下のようにする。

「var offsetY」の値を「-(($window.scrollTop() – offsetPositions.top)/ 17)」から
「$window.scrollTop() – offsetPositions.top -(($window.scrollTop() – offsetPositions.top)/ 17)」に変更するだけ。

<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
jQuery(function($){
  var $window = $(window);
 
  $('.content').each(function(index) {
    var $self = $(this);
    var offsetPositions = $self.offset();
 
    $(window).scroll(function() {
      // この領域がブラウザに表示されている場合
      if (($window.scrollTop() + $window.height()) > offsetPositions.top && ((offsetPositions.top + $self.height()) > $window.scrollTop())) {
         var offsetY =  $window.scrollTop() - offsetPositions.top  -(($window.scrollTop() - offsetPositions.top)/ 17);
        var positions = '50%' + offsetY + 'px';
        $self.css('backgroundPosition', positions);
      }
    });
  });
  });
</script>

似たような効果を別の方法で行ってみる。
(背景画像の CSS で fixed を指定)

サンプル

jQuery を以下のように記述

xxxx_factor は速度を調節するための適当な値。

<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
jQuery(function($){
  
  var first$ = $('#first');
  var first_ot = first$.offset().top;
  var first_factor = -0.1;
  
  var second$ = $('#second');
  var second_ot = second$.offset().top;
  var second_factor = -0.1;
  
  var third$ = $('#third');
  var third_ot = third$.offset().top;
  var third_factor = -0.2;
  
  var end$ = $('#end');
  var end_ot = end$.offset().top;
  var end_factor = -0.5;
  
  $(window).scroll(function(){
    var dy = $(this).scrollTop();
     
    first$.css('background-position',  '50% ' + (dy-first_ot) * first_factor + 'px');
    second$.css('background-position', '50% ' + (dy-second_ot) * second_factor + 'px');
    third$.css('background-position', '50% ' + (dy-third_ot) * third_factor + 'px');
    end$.css('background-position', '50% ' + ((dy - end_ot) * end_factor) + 'px');
  });
});
</script>

以下のように記述しても同じ。

$(window).scroll(function(){
    var dy = $(this).scrollTop();
     $('.content').each(function(index) {
      var $self = $(this);
      var offsetPositions = $self.offset();
      var positions;
      switch(index) {
        case 0:
        positions = '50% ' + (dy-offsetPositions.top) * (-0.1 ) + 'px';
        $self.css('backgroundPosition', positions);
        break;
        case 1:
        positions = '50% ' + (dy-offsetPositions.top) * (-0.1 )  + 'px';
        $self.css('backgroundPosition', positions);
        break;
        case 2:
        positions = '50% ' + (dy-offsetPositions.top) * (-0.2 )  + 'px';
        $self.css('backgroundPosition', positions);
        break;
        case 3:
        positions = '50% ' + (dy-offsetPositions.top) * (-0.5 )  + 'px';
        $self.css('backgroundPosition', positions);
        break;
        default:
        break;      
      }  
     });
  });

他の要素にも効果を与える

サンプル

jQuery での効果のためのパラメータを、以下のような HTML5 のデータ属性を使って指定。

  • data-speed:値が大きいほど遅くなる。負の値は下方向に動く。
  • data-offsety:トップからの距離の調整

また効果を与える要素にクラス「movingElement」を追加。

HTML
変更箇所は「<!–*–>」が付いた3箇所。

<body>
<div id="wrapper">
<div id="first" class="content">
    <!--*--><p class="title movingElement" data-speed="-1.5" data-offsety="100">CSS Parallax 4</p>
    <div class="inner">
      <h1>1. Lorem ipsum dolor</h1>
      <p>Ducimus, deleniti, minus minima delectus... </p>
    </div>
  </div>
 
  <div id="second" class="content">
    <div class="inner">
      <h2>2. Facilis, molestias</h2>
      <p>laboriosam, asperiores quisquam ...</p>
    </div>
  </div>
 
  <div id="third" class="content">
    <div class="inner">
      <h2>3. Quod, illum fuga</h2>
      <p>Laudantium, accusamus, sit... </p>
    </div>
    <!--*--><img src="images/picture01.jpg" class="movingElement" data-speed="1.4" data-offsety="1200"  alt="" />
  </div>
 
  <div id="end" class="content">
    <!--*--><h2 class="movingElement" data-speed="0.8" data-offsety="3180">The End.</h2>
  </div>
</div>
</body>

以下の3つの要素を動かすための jQuery の記述を追加

<p class=”title movingElement” >
<img class=”movingElement” >
<h2 class=”movingElement” >

HTML で指定したデータ属性の値は、以下のようにして取得することができる

$(セレクタ).data(データ属性の「data-」を除いた部分);

<p class="title movingElement" data-speed="-1.5" data-offsety="100">
  
$('.title').data('speed'); // -1.5
$('.title').data('offsety'); // 100

jQuery

<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
jQuery(function($){
  var $window = $(window);
 
  $('.content').each(function(index) {
    var $self = $(this);
    var offsetPositions = $self.offset();
 
    $(window).scroll(function() {
      if (($window.scrollTop() + $window.height()) > offsetPositions.top && ((offsetPositions.top + $self.height()) > $window.scrollTop())) {
        var offsetY =  -(($window.scrollTop() - offsetPositions.top)/ 17); 
        var positions = '50%' + offsetY + 'px';
        $self.css('backgroundPosition', positions);
        //追加部分
        $('.movingElement', $self).each(function(index) {
                var $movingElement = $(this);
                var yPos = -($window.scrollTop() / $movingElement.data('speed')) + $movingElement.data('offsety');
                $movingElement.css('top', yPos);
        });
        //ここまで
      }
    });
  });
});
</script>