指定した秒数ごとに画像がスライドするカルーセル

jQueryを使ったカルーセルプラグインはたくさんあるのであまり困る事は無いと思いますが、試しに自分で作ってみたので2回に分けてカルーセルの作り方を記事にします。

1回目は指定した秒数ごとに画像がスライドする無限ループのカルーセルを作ります。2回目は無限ループに加え、ボタンを画像分用意し、クリックするとボタンに対応した画像が表示されると言ったものに改造して行きます。(余裕があれば3回の記事にし、プラグイン化しようと思います。)

プログラムの流れは下記のような流れに従って作ります。

  • 画像の数や幅などの初期設定を行う。
  • 画像が左にスライドするアニメーションを作る。
  • このアニメーションをメソッド化する。
  • 指定した秒数でこのメソッドを実行させる。

まずデモで完成形をご覧ください。

View Demo

それではコードを解説して行きます。

HTML

HTMLは下記のようなソースコードになります。

HTML Code

<div id="carousel">
	<div class="window">
		<div class="images">
			<ul>
				<li><img src="img/img_c-photo01.jpg" width="360" height="270" alt="" />/li>
				<li><img src="img/img_c-photo02.jpg" width="360" height="270" alt="" /></li>
				<li><img src="img/img_c-photo03.jpg" width="360" height="270" alt="" /></li>
				<li><img src="img/img_c-photo04.jpg" width="360" height="270" alt="" /></li>
				<li><img src="img/img_c-photo05.jpg" width="360" height="270" alt="" /></li>
				<li><img src="img/img_c-photo06.jpg" width="360" height="270" alt="" /></li>
			</ul>
		</div>
	</div>
</div>

カルーセルの説明図04

図にするとこんな感じです。div#carouselの中にdiv.windowがあります。div.windowの役目は画像を表示する領域の指定です。画像(img要素)はul liでマークアップし、div.imagesで包みます。このdiv.imagesを一定時間ごとに左へスライドさせます。

初期設定

まずは初期設定です。ここでは使い回しそうな値を変数に入れておきます。

jQuery Code

$(function() {
	var carousel = $('div.images');
	var carouselUl = carousel.children();
	var carouselLi = carouselUl.find('li');
	var imageWidth = carouselLi.find('img').width();
});

初期設定ではそれぞれの値を変数に入れておきます。

var carousel
スライドさせる画像リストを梱包するdiv。(実際にスライドさせるdiv)
var carouselUl
画像リストul要素。
var carouselLi
画像リストli要素。
var imageWidth
画像(img要素)の幅。指定した秒ごとにこの幅分スライドする。

カルーセル説明図05

今回作るカルーセルは画像を無限にスライドさせます。無限ループをすると言う事は、最後の画像が表示されたら画像リストを元の位置(座標0,0)に戻す必要があります。
この際に画像リストが1組しかないと、最後の画像が左にスライドする事無く元の位置に戻るため、きれいなアニメーションになりません。
この状態を回避するにはもう1組の画像リストを用意し、2組目の画像リストが表示された時にdiv.images(var carousel)を元の位置に戻してあげればいいわけです。

カルーセル説明図06

要素を複製するには.clone()メソッドを利用します。そして複製した要素をdiv.imagesに追加します。要素を追加するには.appendTo()を利用します。

これでdiv.imagesには2つのul要素を内包しました。このdiv.imagesには幅をセットします。幅を指定するには.css('property', 'value')を利用します。
幅の値は(画像の幅 × 画像の数) × 2で求めらるので次のようなコードになります。

jQuery Code

carouselUl.clone().appendTo(carousel); //カルーセルする画像リストを複製して要素に追加
carousel.css('width', carouselLi.length * imageWidth * 2); //幅を設定

アニメーションの作成

いよいよアニメーションの部分に入ります。画像の幅分左にスライドするアニメーションを作ります。アニメーションは下図のようにdiv.images(carousel)を指定した秒ごとにimgの幅分(imageWidth)スライドすると言うものです。

表示領域のdiv.windowにはCSSでposition: relative;を記述してます。この左端を起点にdiv.imagesをposition: absolute;で絶対配置し、jQueryのanimateメソッドでleftプロパティを操作します。

カルーセル説明図07

animateメソッドは.animate(params, [duration], [easing], [callback])のような書式になります。paramsにはcssのプロパティを、durationにはアニメーションの動作時間をミリ秒で、または'slow'や'normal'、'fast'などのキーワードで、easingにはイージングを指定します(easingプラグインを入れてない場合は'liner'か'swing'のみ)。callbackにはアニメーションが終わった後に実行するメソッドを指定します(コールバック関数と言います)

まずは左に画像の幅分スライドするアニメーションを記述します。

jQuery Code

carousel.animate({'left' : '-=' +(imageWidth)}, 'slow'});

これだけでは1回しかアニメーションは実行されません。常にアニメーションをさせるにはsetInterval()を利用します。
setIntervalを利用すると指定した秒数ごとに実行するメソッドを呼び出す事が出来ます。setIntervalは次のような書式になります。

jQuery Code

setInterval(function() {
	Do something
},ミリ秒);

先ほど記述したアニメーションをメソッド化してDo somethingの所で指定した秒数ごとに呼び出すようにしましょう。

jQuery Code

function carouselAnimate() {
	carousel.animate({'left' : '-=' +(imageWidth)}, 'slow'});
}
setInterval(function() {
	carouselAnimate();
},2000);

これで2000ミリ秒毎にcarouselAnimate()が呼び出されるので、2000ミリ秒毎にdiv.images(carousel)がimageWidth分左にスライドして行きます。

さて、ここまでのコードを1度まとめて見てみましょう。

jQuery Code

$(function() {
	//初期設定
	var carousel = $('#images');
	var carouselUl = carousel.children();
	var carouselLi = carouselUl.find('li');
	var imageWidth = carouselLi.find('img').width();
	carouselUl.clone().appendTo(carousel); //カルーセルする画像リストを複製して要素に追加
	carousel.css('width', carouselLi.length * imageWidth * 2); //幅を設定
	//スライドアニメーション
	function carouselAnimate() {
		carousel.animate({'left' : '-=' +(imageWidth)}, 'slow'});
	}
	//指定した秒数ごとの処理
	setInterval(function() {
		carouselAnimate();
	},2000);
});

無限ループの動作を作る

さて、このままではdiv.imagesは永遠に左にスライドし続けてしまいます。さきほどちょっと触れた無限ループの動作を作って行きます。

スライドアニメーションを無限ループにするためには複製した2組目の画像リストの1番目の画像が表示された後直後に、div.images(carousel)を元の位置(座標0,0)に戻してあげます。

カルーセル説明図08

そのためには複製された2組目の画像の1枚目を特定する必要があります。そのためにはカウントアップする変数を用意して、表示領域に表示されている画像が何枚目かを特定します。仕組みは下記のようになります。

  1. 初期値0の変数countを用意。
  2. アニメーションメソッドcarouselAnimate()が1回実行されるたびにcounterの値に1を足す。
  3. counterの値を画像の枚数(carouselLi)で割って余りが0になれば複製した要素の1枚目になる。
  4. div.images(carousel)の座標を元の位置に戻す。
  5. countを0に戻す。

この動作を繰り返せば無限ループが実現出来ます。
現在まで出来たコードに変数countを追加し、3の条件を判定するメソッドを追加します。そしてアニメーションメソッドのcarouselAnimate()の中で呼び出される.animate()のコールバック関数で条件判定のメソッドを実行します。

jQuery Code

$(function() {
	var count = 0; //カウンター
	===== 中略 =====
	function carouselAnimate() {
		count ++; //アニメーションする度にカウンター変数を1ずつ加算して行く
		carousel.animate({'left' : '-=' +(imageWidth)}, 'slow',
			//コールバック関数で条件メソッドを呼び出す
			function(){
				positionInit();
		});
	}
	//現在の表示されている画像を判別するメソッド
	function positionInit() {
		if(!(count % imageLength)) { //カウンターの数を画像の数で割った余りがゼロなら
			carousel.css({'left': 0}); //div#imagesを左端に戻す
			count = 0; //カウンターを初期化
		}
	}
});

これで無限ループするカルーセルが出来上がりました。長くなりましたが完成したコードは下記のようになります。

jQuery Code

$(function() {
	//初期設定
	var count = 0; //カウンター
	var carousel = $('#images'); //カルーセルする画像が梱包されているdiv
	var carouselUl = carousel.children();
	var carouselLi = carouselUl.find('li'); //カルーセルする画像リスト
	var imageWidth = carouselLi.find('img').width(); //画像の幅
	var imageLength = carouselLi.length; //画像の数
	carouselUl.clone().appendTo(carousel); //カルーセルする画像リストを複製して要素に追加
	carousel.css('width', carouselLi.length * imageWidth * 2); //カルーセルする画像リストの横幅を設定
	//アニメーション
	function carouselAnimate() {
		count ++; //アニメーションする度にカウンター変数を1ずつ加算して行く
		carousel.animate({
			'left' : '-=' +(imageWidth)
		}, 'slow',
			function(){
				positionInit()
			}
		);
	}
	//現在の表示されている画像を判別するメソッド
	function positionInit() {
		if(!(count % imageLength)) { //カウンターの数を画像の数で割った余りがゼロなら
			carousel.css({'left': 0});
			count = 0;
		}
	}
	setInterval(function() {
		carouselAnimate();
	},2000);
});

説明も長く、難しかったかもしれませんが、仕組みを知ると色々と応用が効いてくると思います。デモをダウンロード出来るようにしておきますので是非試して見てください。

Download