jquery パララックス(基本的なことに関するメモ)

2013年12月28日

jQuery と CSS を使っての基本的なパララックス効果に関するメモ。

参考にさせていただいたサイト:「パララックスサイトを作ろう」ドットインストール

スクロールで要素を動かす

以下は、スクロールすると3つの要素がそれぞれ動くようにするサンプル。

サンプル用の構造

  • jQuery を読み込む
  • jQuery を記述する pallarax.js を読み込む
  • CSS(pallarax.css) を読み込む
  • 3つの div 要素に class で、幅、高さ、位置(top)、ポジション(fixed)を指定
  • 3つの div 要素に id で位置(left)、色を指定
  • body 要素にはある程度の高さ(ここでは3000px)を指定

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() を利用。

offset()
マッチした最初の要素の、ドキュメントの左上からの相対位置を返す
戻り値: top(上からの位置) と left(左からの位置)をプロパティに持つオブジェクト
var pos1 = $('#box1').offset();
//top(上からの位置): pos1.top 
//left(左からの位置): pos1.left

スクロール距離(量)を取得

ドキュメントがスクロールした時に発生する scroll イベントと scrollTop() を利用して取得

scrollTop()
マッチした最初の要素の、現在の上からのスクロール位置を取得
戻り値: 現在の上からのスクロール位置 (ピクセル)
$(window).scroll(function(){
    var dy = $(this).scrollTop();  //スクロール量
});

css() でその要素の位置をスクロール量を元に動かすには以下のように記述。

  • 変数「pos1」に div 要素(#box1)のドキュメントの左上からの相対位置を格納
  • 変数「dy」にスクロール量を格納
  • css() でスクロール量により要素の位置を変更するように指定
  • 上からの位置:pos1.top(#box1 の上からの位置)にスクロール量の2分の1を加えた値
  • 左からの位置:pos1.left(#box1 の左からの位置)にスクロール量の3分の1を加えた値
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);  //幅をスクロール量によって変更
  });  
});

fixed を使わない場合

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 要素に背景画像を指定

サンプル用の構造

  • 3つの div 要素を作成し、CSS で背景画像をそれぞれ指定
  • div 要素に class で、幅、高さ、マージン、パディングを指定
  • 最後にメッセージを表示する領域を 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;
}

この状態では背景画像が順番に表示され、その後にメッセージ「おわり」が表示される

背景画像を固定

  • background-position を利用して背景画像が固定されている(貼り付いている)ように見せる
  • このサンプルでは x 方向(横方向)には動かさないので「0」を、y 方向にはスクロール分(dy)を指定
  • 以下の例は最初の画像(#bg1)が貼り付いているように見え、その他の画像はスクロールに合わせて動く

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>)のスタイルを指定

  • opacity を 0 に指定して最初は透明にしておく
  • position を fixed に指定
#end_msg {
  font-size: 40px;
  font-weight: bold;
  color: #799B5E;
  opacity: 0;
  position: fixed;
}

このサンプルでは、文字は以下のような条件で出現させる。

  • 3つ目の画像がトップに来た時点(dy > 800)でスクロール量に合わせてパシティを上げる(それ以外の場合はオパシティを「0」に指定)
  • 3つ目の画像が見えなくなった時点でオパシティが「1」になるようオパシティに、スクロール量を画像の高さで割った値を指定
  • トップからの位置を「top」で指定。CSS で「fixed」を指定しているので、スクロールしても固定して表示される
  • 文字が左側から右側に動くように、左からの位置(left)をスクロール量に合わせて変化させる
  • 但し、あまり右側に行過ぎないように、変数(dx)を作成しスクロール量がある値(以下のサンプルでは 440)になったら適当な値に固定する
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)の上でマウスなどのポインティングデバイスが動いている時に発生する。

mousemove(fn)
マッチした要素の mousemove イベントに、イベントハンドラ(関数)をバインドする。
イベントハンドラ関数の第1引数に渡されるイベントオブジェクトには、イベントが発生した位置を表すプロパティとして、以下の4つが設定される。
プロパティ名 説明
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);
    });
});
  • #container の横方向、縦方向の中心の座標(center_x,center_y)を取得して変数に代入
  • マウスの横方向、縦方向の中心からの距離(dx,dy)を取得して変数に代入
  • マウスの動きに合わせて動かす要素(#box1,#box2,#box3)の位置を中心からの距離(dx,dy)にある係数(適当な値)を掛けて変化させる
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);
    });
});