jQuery と CSS を使っての基本的なパララックス効果に関するメモ。
参考にさせていただいたサイト:「パララックスサイトを作ろう」ドットインストール
以下は、スクロールすると3つの要素がそれぞれ動くようにするサンプル。
parallax1.html
<!doctype html> <html> <head> <meta charset="utf-8"> <title>パララックス</title> <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script src="js/pallarax1.js"></script> <link rel="stylesheet" href="css/pallarax1.css" type="text/css" /> </head> <body> <div id="box1" class="box"></div> <div id="box2" class="box"></div> <div id="box3" class="box"></div> </body> </html>
pallarax1.css
body {
  margin: 0;
  padding: 0;
  height: 3000px;
}
.box {
  width: 40px;
  height: 40px;
  position: fixed;
  top: 10px;
}
#box1 {
  left: 10px;
  background: red;
}
#box2 {
  left: 60px;
  background: blue;
}
#box3 {
  left: 110px;
  background: green;
}
ドキュメント上での表示位置を取得するには、offset() を利用。
var pos1 = $('#box1').offset();
//top(上からの位置): pos1.top 
//left(左からの位置): pos1.left
ドキュメントがスクロールした時に発生する scroll イベントと scrollTop() を利用して取得
$(window).scroll(function(){
    var dy = $(this).scrollTop();  //スクロール量
});
css() でその要素の位置をスクロール量を元に動かすには以下のように記述。
jQuery(function($){
  var pos1 = $('#box1').offset();
  
  $(window).scroll(function(){
    var dy = $(this).scrollTop();
        
    $('#box1').css('top', pos1.top + dy / 2);
    $('#box1').css('left', pos1.left + dy / 3);
  });  
});
3つの要素をばらばらに動かすには、スクロール量を異なる値で割るなどして、それぞれの位置の値を指定する。
pallarax1.js
jQuery(function($){
  var pos1 = $('#box1').offset();
  var pos2 = $('#box2').offset();
  var pos3 = $('#box3').offset();
  
  $(window).scroll(function(){
    var dy = $(this).scrollTop();
    
    $('#box1').css('top', pos1.top + dy / 2);
    $('#box1').css('left', pos1.left + dy / 3);
    
    $('#box2').css('top', pos2.top + dy / 5);
    $('#box2').css('left', pos2.left + dy / 8);
    
    $('#box3').css('top', pos3.top + dy / 7);
    $('#box3').css('left', pos3.left + dy / 4);
  });  
});
位置だけでなく、幅や高さなどもスクロール量によって動的に変更することが可能。
jQuery(function($){
  var pos1 = $('#box1').offset();
  
  $(window).scroll(function(){
    var dy = $(this).scrollTop();
    
    $('#box1').css('top', pos1.top + dy / 2);
    $('#box1').css('left', pos1.left + dy / 3);
    $('#box1').css('width', 40 + dy * 0.3);  //幅をスクロール量によって変更
  });  
});
CSS で .box に「position: fixed」を指定せず「position: relative」を指定する場合は、jQuery でスクロールした分(dy)を「top」の値に追加する。
また、それぞれの要素を並べるために CSS で「top」の値を調整。
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>パララックス</title>
<style>
@charset "utf-8";
body {
  margin: 0;
  padding: 0;
  height: 3000px;
}
.box {
  width: 40px;
  height: 40px;
  /*position: fixed; relative に変更*/
  position: relative;
  /*top: 10px; 削除*/
}
#box1 {
  left: 10px;
  top: 10px;  /*追加*/
  background: red;
}
#box2 {
  left: 60px;
  top: -30px;  /*3つ横に並べるために追加 */
  background: blue;
}
#box3 {
  left: 110px;
  top: -70px;  /*3つ横に並べるために追加 */
  background: green;
}
</style>
</head>
<body>
<div id="box1" class="box"></div>
<div id="box2" class="box"></div>
<div id="box3" class="box"></div>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
jQuery(function($){
  var pos1 = $('#box1').offset();
  var pos2 = $('#box2').offset();
  var pos3 = $('#box3').offset();
  
  $(window).scroll(function(){
    var dy = $(this).scrollTop();
    
    $('#box1').css('top', dy + pos1.top + dy / 2);
    $('#box1').css('left', pos1.left + dy / 3);
    $('#box1').css('width', 40 + dy * 0.3);
    
    $('#box2').css('top', dy + pos2.top - 40 + dy / 5);
    $('#box2').css('left', pos2.left + dy / 8);
    
    $('#box3').css('top', dy + pos3.top - 80 + dy / 7);
    $('#box3').css('left', pos3.left + dy / 4);
    
  });    
});
</script>
</body>
</html>
背景用の画像を用意して div 要素に背景画像を指定
parallax2.html
<!doctype html> <html> <head> <meta charset="utf-8"> <title>パララックス2</title> <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script src="js/pallarax2.js"></script> <link rel="stylesheet" href="css/pallarax2.css" type="text/css" /> </head> <body> <div id="bg1" class="box"></div> <div id="bg2" class="box"></div> <div id="bg3" class="box"></div> <div id="end_msg" class="box">おわり</div> </body> </html>
parallax2.css
@charset "utf-8";
body {
  margin: 0 auto;
  padding: 0;
  height: 3000px;
}
.box {
  margin: 0 auto;
  padding: 0;
  height: 400px;
  width: 960px;
}
#bg1 {
  background: url(../images/bgpic-1.jpg) no-repeat;
}
#bg2 {
  background: url(../images/bgpic-2.jpg) no-repeat;
}
#bg3 {
  background: url(../images/bgpic-3.jpg) no-repeat;
}
この状態では背景画像が順番に表示され、その後にメッセージ「おわり」が表示される
parallax2.js
jQuery(function($){
  
  $(window).scroll(function(){
    var dy = $(this).scrollTop();
    
    $('#bg1').css('background-position', '0 ' + dy + 'px');
  });  
});
2つ目の画像が画面トップに来たら(dy > 400)そこで固定させるには、スクロール量が画像の高さに達したら、同様に background-position を利用して y 方向にスクロール分(dy-400)を指定。「400」は(1つ目の)画像の高さで、すでにスクロールされている量。
それ以外の場合は、「’0 0’」を指定して背景画像は動かさない。
jQuery(function($){
  
  $(window).scroll(function(){
    var dy = $(this).scrollTop();
    
    $('#bg1').css('background-position', '0 ' + dy + 'px');
    
    if(dy > 400) {
      $('#bg2').css('background-position', '0 ' + (dy-400) + 'px');
    }else{
      $('#bg2').css('background-position', '0 0');
    }
  });  
});
3つ目の画像も同様に指定すれば、同じ効果になるが、以下は3つ目の画像は画面トップに来たら、スクロール量より大きな値を指定することで、逆方向(下方向)にずれるような効果にする例。
jQuery(function($){
  
  $(window).scroll(function(){
    var dy = $(this).scrollTop();
    
    $('#bg1').css('background-position', '0 ' + dy + 'px');
    
    if(dy > 400) {
      $('#bg2').css('background-position', '0 ' + (dy-400) + 'px');
    }else{
      $('#bg2').css('background-position', '0 0');
    }
    
    if(dy > 800) {
      $('#bg3').css('background-position', '0 ' + (dy-800) * 1.5 + 'px');
    }else{
      $('#bg3').css('background-position', '0 0');
    }
  });  
});
以下は2つ目の画像は横方向(x方向)にも移動させる例。
jQuery(function($){
  
  $(window).scroll(function(){
    var dy = $(this).scrollTop();
    
    $('#bg1').css('background-position', '0 ' + dy + 'px');
    
    if(dy > 400) {
      //横方向のずれを指定
      $('#bg2').css('background-position', (dy-400) +'px ' + (dy-400) + 'px');
    }else{
      $('#bg2').css('background-position', '0 0');
    }
    
    if(dy > 800) {
      $('#bg3').css('background-position', '0 ' + (dy-800) * 1.5 + 'px');
    }else{
      $('#bg3').css('background-position', '0 0');
    }
  });  
});
出現させる文字( <div id=”end_msg” class=”box”>おわり</div>)のスタイルを指定
#end_msg {
  font-size: 40px;
  font-weight: bold;
  color: #799B5E;
  opacity: 0;
  position: fixed;
}
このサンプルでは、文字は以下のような条件で出現させる。
jQuery(function($){
  
  $(window).scroll(function(){
    var dy = $(this).scrollTop();
    
    $('#bg1').css('background-position', '0 ' + dy + 'px');
    
    if(dy > 400) {
      $('#bg2').css('background-position', '0 ' + (dy-400) + 'px');
    }else{
      $('#bg2').css('background-position', '0 0');
    }
    
    if(dy > 800) {
      $('#bg3').css('background-position', '0 ' + (dy-800) * 1.5 + 'px');
    }else{
      $('#bg3').css('background-position', '0 0');
    }
    
    //文字を出現させる指定
    if(dy > 800) {
      $('#end_msg').css('opacity', (dy-800) /400);
      $('#end_msg').css('top', 200);
      var dx = (dy-800) > 440 ? 440 : (dy-800);
      $('#end_msg').css('left', dx);
    }else{
      $('#end_msg').css('opacity', 0);
    }
  });  
});
今までの例では、背景画像の位置などは直接数値で指定したが、offset().top を利用してあらかじめ変数に格納しておくとよい。
jQuery(function($){
  
  $(window).scroll(function(){
    var dy = $(this).scrollTop();
    var bg2Top = $('#bg2').offset().top;
    var bg3Top = $('#bg3').offset().top;
    var msgPosTop = 200;
    var msgPosLeft = 440;
    
    $('#bg1').css('background-position', '0 ' + dy + 'px');
    
    if(dy > bg2Top) {
      $('#bg2').css('background-position', '0 ' + (dy-bg2Top) + 'px');
    }else{
      $('#bg2').css('background-position', '0 0');
    }
    
    if(dy > bg3Top) {
      $('#bg3').css('background-position', '0 ' + (dy-bg3Top) * 1.5 + 'px');
    }else{
      $('#bg3').css('background-position', '0 0');
    }
    
    if(dy > bg3Top) {
      $('#end_msg').css('opacity', (dy-bg3Top) /bg2Top);
      $('#end_msg').css('top', msgPosTop);
      var dx = (dy-bg3Top) > msgPosLeft ? msgPosLeft : (dy-bg3Top);
      $('#end_msg').css('left', dx);
    }else{
      $('#end_msg').css('opacity', 0);
    }
  });  
});
マウスの動きに合わせて、要素を動かす例。
マウスの動きに合わせて動く div 要素(.box)を3つ作成し、それらを囲む div 要素(#container)を作成。
parallax3.html
<!doctype html> <html> <head> <meta charset="utf-8"> <title>パララックス3</title> <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script src="js/pallarax3.js"></script> <link rel="stylesheet" href="css/pallarax3.css" type="text/css" /> </head> <body> <div id="container"> <div id="box1" class="box"></div> <div id="box2" class="box"></div> <div id="box3" class="box"></div> </div> </body> </html>
parallax3.css
@charset "utf-8";
body {
  margin: 0 auto;
  padding: 0;
  height: 3000px;
}
#container {
  width: 600px;
  height: 300px;
  background: #EEE;
}
  
.box {
  position: fixed;
  opacity: 0.5;
  left: 300px;
}
#box1 {
  width: 40px;
  height: 40px;
  top: 140px;
  background: blue;
}
#box2 {
  width: 60px;
  height: 60px;
  top: 160px;
  background: red;
}
#box3 {
  width: 80px;
  height: 80px;
  top: 180px;
  background: yellow;
}
mousemove(fn) を利用してマウスカーソルの位置を取得。通常、mousemove イベントは、要素(この例では#container)の上でマウスなどのポインティングデバイスが動いている時に発生する。
| プロパティ名 | 説明 | 
|---|---|
| pageX | ページの左上を0とした横位置 | 
| pageY | ページの左上を0とした縦位置 | 
| clientX | ブラウザのドキュメント表示領域の左上を0とした横位置 | 
| clientY | ブラウザのドキュメント表示領域の左上を0とした縦位置 | 
以下は、マウスが div 要素( #container)の中で移動した際に、その座標をコンソールに出力する例。イベントオブジェクト(e)のプロパティ(clientX, clientY)を出力。
jQuery(function($){
  
  $('#container').mousemove(function(e) {
            console.log(e.clientX, e.clientY);
    });
});
jQuery(function($){
  
  $('#container').mousemove(function(e) {
    //#containerの中心の座標
    var center_x = $(this).width() / 2;  
    var center_y = $(this).height() / 2;
    var dx = e.clientX - center_x;  //横方向の中心からの距離
    var dy = e.clientY - center_y;  //縦方向の中心からの距離
    $('#box1').css('left', center_x + dx * 1.1);
    $('#box2').css('left', center_x + dx * 1.3);
    $('#box3').css('left', center_x + dx * 1.5);
    $('#box1').css('top', center_y + dy * 1.1);
    $('#box2').css('top', center_y + dy * 1.3);
    $('#box3').css('top', center_y + dy * 1.5);
    });
});