[jQuery] カーソルの動きに合わせて動くパララックスを作る方法

[jQuery] カーソルの動きに合わせて動くパララックスを作る方法

jQueryのmousemoveイベントの事を勉強したので、このイベントを使ってカーソルの動きに合わせて画像を動かし、パララックス効果を出すサンプルを作ってみました。備忘録も兼ねてその流れをまとめました。

参考にさせて頂いたプラグイン

いろいろコードを覗いてみましたが、jQuery.Smart3D のコードが私にはわかりやすかったので計算式などだいぶ参考にさせて頂きました。

mousemoveイベントについて

mousemoveイベントはマウスが要素上を動いた時に発生し、mousemoveイベントの引数からイベントに関するさまざまな情報を受取ることができます。マウスカーソルの位置もここで取得することができます。

作ったサンプルデモ

Simple3Dmove_Sample|memocarilog-demo
Simple3Dmoveサンプルデモ

作ったサンプルは以下のアドレスからダウンロードできます。

◆ Simple3Dmove_Sampleをダウンロード

カーソルの動きに合わせて動くパララックスを作るコード

HTMLのコード

HTMLは下のようにul要素で囲い、画像をli要素でマークアップします。

<ul id="sample">
	<li><img src="images/kusa1.png" alt="くさ"></li>
	<li><img src="images/hana.png" alt="はな"></li>
	<li><img src="images/kusa2.png" alt="くさ"></li>
	<li><img src="images/syabondama.png" alt="シャボン玉"></li>
</ul>

あとでCSSで画像を position: absolute で全部重ねあわせますが、下の方に配置した画像が上に重なることになるので並べ順に注意です。

CSSのコード

まず、親要素となる #sample へ position:relative を指定し、子要素の li へ position: absolute を指定します。width と height は子要素の li の方を若干親要素より大きいサイズに指定します。

#sample {
	/* jQueryに必要な指定 */
	position: relative;
	overflow: hidden;
	margin:0 auto 50px ;
	width: 700px;
	height: 450px;
	
	/* 背景とフレームの指定 */
	outline: solid 2px #ddd;
	border: solid 20px #fff;
	background: url(images/bg.jpg);
	box-shadow: 1px 1px 50px RGBA(0,0,0, .2) inset ;
}
#sample li{
	position: absolute;
	top:-25px;
	left: -50px;
	width: 800px;
	height: 500px;
}

#sample li の top値 と left値 は ul要素とli要素を中央で揃える為に指定しています。(計算式→ ul縦幅 – li縦幅)÷ 2 = top値 / ul横幅 – li横幅)÷ 2 = left値)

次に、各画像のCSS指定をします。各画像の表示位置を指定するため、ここでも position: absolute にし適当な位置を指定します。

/* くさ1 */
#sample li:nth-child(1) img{
	position: absolute;
	bottom:0;
}
/* はな */
#sample li:nth-child(2) img{
	position: absolute;
	bottom:50px;
}
/* くさ2 */
#sample li:nth-child(3) img{
	position: absolute;
	bottom: -30px;
}
/* シャボン玉 */
#sample li:nth-child(4) img{
	position: absolute;
	bottom: 150px;
	opacity: 0.4;
}

jQueryのコード

jQuery本体を読み込み、4行目の「$(‘#sample’)」の部分に親要素のIDを指定します。

<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script>
$(function(){
		var thisObj = $('#sample');
		// 親ボックスのオブジェクトを作る
        if (thisObj.length == 0) return false;
        // thisObj に何も入っていなければ false を返す
        var item = thisObj[0];
		// 親ボックスオブジェクトから構造の情報を取り出す(ul liなどの構造)

以下のように各要素の縦橫のサイズなどを取得します。

		var liWidth = $('>li', item).width()
		// li要素の横幅を取得
		var liHeight = $('>li', item).height()   
		// li要素の縦サイズを取得
		
		var ulWidth = thisObj.width();
		// 親要素の横幅取得
		var ulHeight = thisObj.height();
		// 親要素の縦サイズを取得
		
		var offset_x = liWidth - ulWidth;
		// ↑ liから親ボックスの横の大きさをひいた数	
		var offset_y = liHeight - ulHeight;
		// ↑ liから親ボックスの縦の大きさをひいた数
		
		var itemLi = thisObj.find('li');
		// thisObjからli要素を取り出す		

次にmousemoveイベントで取得できるカーソルの位置を使って、画像が動ける範囲などを計算します。

	thisObj.mousemove(function(e){
	// ↑「e」に現在のカーソル位置の情報などが入る。
	
	// x方向の計算 ========
		var cursorX = e.clientX - thisObj.offset().left;
		// e.clientY → 表示画面上からの距離
		// thisObj.offset().top → ドキュメント左からの距離
		// cursorX → 親ボックス左からみたカーソルの相対位置
		
		(cursorX > ulWidth) ? cursorX = ulWidth : cursorX ;				
		// 親ボックスからみたカーソルの位置が横幅より大きくなった場合は ulwidth値を入れる
		
		var centerX = (cursorX / ulWidth * offset_x) - offset_x / 2 ;
		// X方向中心からみたカーソル位置の計算(中心を0とする)
	
	// y方向の計算 ========
		var cursorY = e.clientY - thisObj.offset().top + $('html').scrollTop();
		// e.clientY → 表示画面上からの距離
		// thisObj.offset().top → ドキュメントから上の距離
		// cursorY → 親ボックス上からみたカーソルの相対位置
						
		(cursorY > ulHeight) ? cursorY = ulHeight : cursorY ;				
		// 親ボックスからみたカーソルの位置が縦幅より大きくなった場合は ulHeight値を入れる
										
		var centerY = (cursorY / ulHeight * offset_y) - offset_y / 2;
		// Y方向中心からみたカーソルの位置の計算(中心を0とする)	

つづいてli要素を移動させる処理をします。カーソルの移動値から計算した値を新しい移動先として、CSSのleft値とtop値をちくいち変更します。カーソルが動くごとにちくいち計算し移動先値も変わっていく為スムーズに画像が動いているように見えます。

	// li要素を移動させるループ ========	
		for (var i=1; i<= itemLi.length; i++){
					
		// x方向の移動処理				
			var liLeft = parseFloat($(itemLi[i-1]).css('left'));
			// liのleft値を取得.parseFloat → 文字列を数値に変換する
			var newLeft = centerX * (i / itemLi.length) - offset_x / 2;
			// liの個数分だけそれぞれ違うnewLeft値を計算する
			$(itemLi[i-1]).css('left', (newLeft + liLeft*5) / 6);	
			// それぞれのliのCSS'left'値を変更する。/6 の数値を大きくすると動きも小さく		
						
		// Y方向の移動処理
			var liTop = parseFloat($(itemLi[i-1]).css('top'));
			// liのtop値を取得.parseFloat → 文字列を数値に変換する
			var newTop = centerY * (i / itemLi.length) - offset_y / 2;
			// liの個数分だけそれぞれ違うnewTop値を計算する						
			$(itemLi[i-1]).css('top', (newTop + liTop*5) / 6);
			// それぞれのliのCSS'top'値を変更する。/6 の数値を大きくすると動きも小さく
		
		} // li要素を移動させる処理ここまで
	});	
});
</script>

この計算式では自動的にliごとに違った移動値を出し、liそれぞれ移動先が変わることで奥行きがある感じを出しています。掛ける数や割る数を変えるとまた違った動きにもなります。

コメントを沢山書いたので長いコードに見えますが、実際はそんなに長くないです。サンプルの項目からダウンロードできるファイルでコメントのない、一連のコードが見れます。親要素を指定するだけで簡単に3Dっぽい動きが作れます。

Related Article

2 Comments & Tracbacks

  • ナカムラ 2014-05-02 2:24 PM

    丁寧なコメントで良く理解することができました!

    Reply

    • saori 2014-05-02 7:11 PM

      おお!ナカムラさん(^o^)拙コードですが見て下りありがとうございます…!

      Reply

Leave a Comment

saori にコメントする コメントをキャンセル

Emailは公開されません。*は必須項目です。


*


Categorys

Tags

CSS3 ダッシュボード ヘッダー トラブル コードサンプル スライドショー コンテンツ 素材 jQueryプラグイン Facebook php 引っ越し お知らせ JavaScript CSS カテゴリー Shareボタン IE 投稿タイプ seo Photoshop HTML5 レスポンシブ サイドバー ナビゲーション タクソノミー WPセキュリティ Git カスタムメニュー Macアプリ PHPリファレンス SVG query_posts API WP使い方 iTunes データベース コメント function RSS 条件分岐 get_posts() スマートフォン Sass/Compass マルチサイト機能