WEBOPIXEL

jQueryで作るボタンでスライドするローテーションバナー

Posted: 2010.12.27 / Category: javascript / Tag: 

以前に「jQueryで作るスライドするローテーションバナー」というのを作成したのですが、結構シンプルな作りでちょっと今の時代のあれじゃないよね。ということでボタンをクリックすると次の画像に進んだり戻ったり、ページネーション的なボタンを追加することで、ちょっとだけ実用的なものにしたいと思います。

Sponsored Link

demo

html+cssを制作する

まずはhtmlとcssですね。
「id=banner」divにはメインとなるローテーションさせる画像をリストで配置。
その下の「id=btn-prev」「id=btn-next」は次へ進むボタンと戻るボタンです。
「id=pagenation」にはページネーションボタンが配置されています。
divがちょっと余分じゃね? って感じがしますが、横並びでセンター揃えにしたい場合ちょっと複雑になってしまうようです。
(もっと良い方法があるかもしれませんが……)

html

	<div id="container">
		<div id="banner">
			<ul>
				<li><a href="img/01.jpg"><img src="img/01.jpg" width="320" height="213" /></a></li>
				<li><a href="img/02.jpg"><img src="img/02.jpg" width="320" height="213" /></a></li>
				<li><a href="img/03.jpg"><img src="img/03.jpg" width="320" height="213" /></a></li>
				<li><a href="img/04.jpg"><img src="img/04.jpg" width="320" height="213" /></a></li>
			</ul>
		</div>
		<a href="#"><img src="img/btn_prev.gif" width="30" height="30" id="btn-prev" /></a>
		<a href="#"><img src="img/btn_next.gif" width="30" height="30" id="btn-next"  /></a>
		<div id="pagenation">
			<ul>
				<li><a href="#"><img src="img/pagenation.gif" width="12" height="24" /></a></li>
				<li><a href="#"><img src="img/pagenation.gif" width="12" height="24" /></a></li>
				<li><a href="#"><img src="img/pagenation.gif" width="12" height="24" /></a></li>
				<li><a href="#"><img src="img/pagenation.gif" width="12" height="24" /></a></li>
			</ul>
		</div>
	</div>
	

cssはとりあえずこんな感じにすれば、あるていど配置してくれるはずです。

css

	#container {
	width: 326px;
	margin: 50px auto;
	}
	#banner {
		border: 3px solid #CCCCCC;
		margin-bottom: 5px;
	}
	#banner ul {
		list-style: none;
		position: relative;
		margin-left: 0px;
		overflow: hidden;
		width:320px;
		height: 213px;
	}
	#banner ul li {
		float: left;
		width: 320px;
		position: absolute;
	}
	div#pagenation {
	   position: relative;
	   overflow: hidden;
	   top: -30px;
	}
	
	div#pagenation ul {
		position:relative;
		left:50%;
		float:left;
		list-style: none;
	}
	div#pagenation li {
	   position:relative;
	   left:-50%;
	   float:left;
	   margin: 0 2px;
	   
	}
	div#pagenation li a {
		width:12px;
		height:12px;
		overflow:hidden;
		display:block;
		background-image:url(img/pagenation.gif);
		background-position:0 0;
	}
	div#pagenation li.active a,
	div#pagenation li a:hover {
		background-position:0 12px;
	}
	div#pagenation li a img {
		visibility:hidden;
		display: none;
	}
	#btn-prev {
		position: relative;
		left: -40px;
		top: -130px;
	}
	#btn-next {
		position: relative;
		left: 305px;
		top: -130px;
	}
	

このまま進めてもいいのですが、進むボタンとかページネーションボタンはサーチエンジンやjavasucriptが使用できない環境では、無駄な感じがします。
これらはjavascript側で配置した方がいいかもしれません。
ということでhtmlの「btn-prev」「btn-next」「pagenation」の部分は削除しておきます。

1.グローバル変数

準備ができたのでjavascriptのコードを作成していきましょう。
まずは使用するグローバル変数です。

javascript

		var _imgSize = 320;	//画像のサイズ
		var _imgNum = 0;	//画像の枚数
		var _current = 0;	//現在の画像
	
_imgSize
画像のwidthを格納する変数です。スクリプトで取得しますので設定する必要はありません。
_imgNum
画像の枚数です。0からカウントされますので4枚の画像をローテーションさせる場合は「3」となります。
この変数はスクリプトでliの数だけ自動でカウントしますので変更の必要はありません。
_current
現在の画像の位置です。0なら1枚目、1なら2枚目を表示しているということです。
これも基本的に変更する必要はありませんが、2番目からスタートさせたいという奇特な方がおりましたら「1」としておいてください。

2.各画像の配置

htmlの最後の部分で削除した画像の配置や、メイン画像を指定して配置します。

		//各ボタンの配置
		$('#container').append('<a href="#"><img src="img/btn_prev.gif" width="30" height="30" id="btn-prev" /></a><a href="#"><img src="img/btn_next.gif" width="30" height="30" id="btn-next"  /></a><div id="pagenation"><ul></ul></div>');
	

まずは「btn-prev」「btn-next」「pagenation」を配置します。
「append」とすれば「id=banner」の下に配置してくれます。
「pagenation」のliがないのは、メイン画像の数によって動的に変化するからです。

		//画像サイズ取得
		_imgSize = $('#banner ul li img').width();
		//メイン画像の数だけ繰り返す
		$('#banner ul li').each(function(){
			//画像をずらして外に配置
			$(this).css('margin-left', -_imgSize);
			//画像の数だけページネーションボタンを作成
			if (_imgNum == _current) {
				//currentだったらアクティブ、
				$('#pagenation ul').append('<li class="active"><a href="#"><img src="img/pagenation.gif" width="12" height="24" /></a></li>');
				//currentのメインの画像のみ表示
				$(this).css('margin-left', '0px');
			} else {
				$('#pagenation ul').append('<li><a href="#"><img src="img/pagenation.gif" width="12" height="24" /></a></li>');
			}
			//ループの数をカウントして_imgNumに入れる
			_imgNum++;
		});
	

メイン画像の数だけ処理するものはここに書いてます。
まずはメイン画像を「_imgSize」(画像サイズ)分だけマイナスすることですべて見えなくしています。
次に前述の「pagenation」のliの配置です。
「_current」(最初の画像)の場合は「active」にして他の画像と区別します。
同時にメイン画像も「_current」のもだけ「0px」に戻して見えるようにしています。

3.ボタン処理

	//ボタンをクリック
	$('#btn-next').click(function(){
		imageMove(_current +1);
	});
	$('#btn-prev').click(function(){
		imageMove(_current -1);
	});
	//ページネーションクリック
	$('#pagenation ul li').click(function() {
		var thisNum = $('#pagenation li').index(this);
		//押したボタンが現在の画像じゃなかったら実行
		if(thisNum != _current) {
			imageMove(thisNum);
		}
	});
	

ボタンをクリックされたときの処理です。
基本的に後述する「imageMove」というメソッドの引数に表示させたい画像のインデックスを渡します。
「_current」には現在の画像の位置(インデックス)が入っているので、「_current +1」を渡せば次の画像が表示されますね。また戻る場合は「_current -1」です。

ページネーションがクリックされた場合は「$(‘#pagenation li’).index(this)」で押されたリストのインデックスが取得できます。
そのまま渡すと、押されたボタンとすでに表示されている画像が同じだった場合奇妙なことになってしまうので、クリックされたインデックスと「_current」が違う場合のみ実行しましょう。

4.画像のスライド処理

ここからが肝となる画像をスライドさせる処理です。
「imageMove」というメソッドを作成します。引数は「next」としてこの中にスクリプトを書いていきます。

		function imageMove(next) {
		}
		

画像の再配置の準備

現在画像はすべて左側に配置していますね。
これだと右ボタンを押しても、左ボタンを押しても左側からスライドしてしまうので、押されたボタンに応じて画像の再配置を行います。

現在の画像(_current)と次の画像番号(next)と比較して小さかったら左に、大きかったら右に配置します。

次の画像が現在の画像より小さかったら画像サイズ分だけ左に配置

			var pos;
			if (_current < next) {
				pos = -_imgSize;
			} else {
				pos = _imgSize;
			}
		

とりあえず「pos」という変数に入れておき、後で配置するときにこの変数を使用します。

現在の画像が最初、最後だったら

現在の画像が最後(_imgNum)だったら次の画像はないので表示できないですよね。
その場合は表示する画像を最初に戻してあげましょう。逆に最初の画像だったらその前はないので最後の画像を指定します。

			if (next == _imgNum) {
				next = 0;
			} else if(next == -1) {
				next = (_imgNum-1);
			}
		

これで次の画像を配置する準備が整いました。

次の画像を配置してスライドさせる

次の画像を配置してスライドさせる

リストで並べられた画像の中から次の画像(next)だけ選択する必要がありますね。
セレクター後に「.eq(index)」とすれば、リストの中の任意のものだけ選択することができます。
indexには番号を指定しますが、当然「next」ですね。

			$("#banner li").eq(next)
			.css("margin-left", pos)
			.animate({marginLeft: "0"},"fast");
		

あとはcssで配置して、おなじみの「animate」メソッドで移動させましょう。

現在の画像を配置してスライドさせる

次の画像と同時に現在の画像も枠の外に移動させる必要があります。

			$("#banner li").eq(_current)
			.animate({marginLeft: -pos},"fast");
		

現在の画像はすでに配置されているので、移動処理だけですね。
移動方向は次の画像と逆方向になるので「-pos」です。

ページネーションの更新

ページネーションの部分も何もしないと同じ箇所がアクティブになったままです。
現在のリストのアクティブを消し、次のリストをアクティブにしましょう。

			$('#pagenation li').eq(_current).removeClass('active');
			$('#pagenation li').eq(next).addClass('active');
		

現在の画像番号を更新

すべての処理が終わったら現在の画像番号(_current)に次の番号(next)を入れて更新します。

			_current = next;
		

自動的に画像を切り替える

せっかくなので前回作成したタイマーイベントで画像を切り替える機能も追加してみましょう。
インデックスを渡せば切り替えてくれる「imageMove」という処理ができていますので、一定時間おきにこれを実行するだけです。

		setInterval(function(){
			imageMove(_current +1);
		}, 3000);
	

最終的なコード

まだまだ粗がありますがこれで完成です。

(function($) {
$(function(){
	var _imgNum = 0;	//画像の枚数
	var _imgSize = 0;	//画像のサイズ
	var _current = 0;	//現在の画像
	var _timer = 3000;	//タイマー時間
	
	//各ボタンの配置
	$('#container').append('<a href="#"><img src="img/btn_prev.gif" width="30" height="30" id="btn-prev" /></a><a href="#"><img src="img/btn_next.gif" width="30" height="30" id="btn-next"  /></a><div id="pagenation"><ul></ul></div>');
	
	//画像サイズ取得
	_imgSize = $('#banner ul li').width();
		
	//メイン画像の数だけ繰り返す
	$('#banner ul li').each(function(){
		//画像をずらして外に配置
		$(this).css('margin-left', -_imgSize);
		//画像の数だけページネーションボタンを作成
		if (_imgNum == _current) {
			//currentだったらアクティブ、メインの画像は表示
			$('#pagenation ul').append('<li class="active"><a href="#"><img src="img/pagenation.gif" width="12" height="24" /></a></li>');
			$(this).css('margin-left', '0px');
		} else {
			$('#pagenation ul').append('<li><a href="#"><img src="img/pagenation.gif" width="12" height="24" /></a></li>');
		}
		//ループの数をカウントして_imgNumに入れる
		_imgNum++;
	});
	
	//一定時間ごとにimageMoveを実行
	var loopSwitch = setInterval(loop, _timer);
	function loop() {
		imageMove(_current +1);
	}
	
	//ボタンをクリック
	$('#btn-next').click(function(e){
		e.preventDefault();
		imageMove(_current +1);
	});
	$('#btn-prev').click(function(e){
		e.preventDefault();
		imageMove(_current -1);
	});
	//ページネーションクリック
	$('#pagenation ul li').click(function(e) {
		e.preventDefault();
		var thisNum = $('#pagenation li').index(this);
		//押したボタンが現在の画像じゃなかったら実行
		if(thisNum  != _current) {
			imageMove(thisNum );
		}
	});
	
	function imageMove(next) {
		//ループ時間リセット
		clearInterval(loopSwitch);
		loopSwitch = setInterval(loop, _timer);
		//次の画像が次の画像より多きかったら右に配置(小さかったら左)
		var pos;
		if (_current < next) {
			pos = -_imgSize;
		} else {
			pos = _imgSize;
		}
		
		//次の画像が最後なら1枚目、1枚目なら最後
		if (next == _imgNum) {
			next = 0;
		} else if(next == -1) {
			next = (_imgNum-1);
		}

		//次の画像を動かす
		$("#banner li").eq(next)
		//次の画像を次の位置に配置
		.css("margin-left", pos)
		.animate({
			marginLeft: "0"
		},"fast");
		
		//現在の画像を動かす
		$("#banner li").eq(_current)
		.animate({
			marginLeft: -pos
		},"fast");
		
		//ページネーション現在のを消し次のをアクティブに
		$('#pagenation li').eq(_current).removeClass('active');
		$('#pagenation li').eq(next).addClass('active');
		
		//現在の番号を次の番号にする。
		_current = next;
	}
});
})(jQuery);