アド企画 制作部
アド企画 制作部
 

jQuery(JavaScript)でタップ中・オンマウス中に画像を順次切り替える(PC・スマホ・タブレット対応)

jQuery(JavaScript)でタップ中・オンマウス中に画像を順次切り替える(PC・スマホ・タブレット対応)


動画共有サイト等によくある、画像にマウスを乗せている間、順次画像が切り替わるスクリプトを作成してみた。
ハマりにハマって、最終的には思ったとおりの挙動にする事ができたが、実際にはどんなコードで動いているのかは調べていないので…。

実際の挙動:画像を順次切り替える

次の様なものを作成する方法を紹介していく。

  • title_a1
  • title_a2
  • title_a3
  • title_a4
  • title_a5
  • title_b1
  • title_b2
  • title_b3
  • title_b4
  • title_b5

HTML及びCSS


まず、HTMLでリストを作成し、CSSで最初の一枚以外を隠すように、ul.image_items に横幅(width)・高さ(height)を設定し、overflow:hidden; とする。

リストに使用する画像の表示サイズは、ul.image_items に指定したサイズより大きくしないとズレてくる。

<div class="image_item">
		<ul class="image_items">
			<li class="item"><a href="#" title="title_a1"><img src="http://dev.adokikaku.com/wp-content/uploads/2015/04/sample_a1.jpg" alt="title_a1" width="300" /></a></li>
			<li class="item"><a href="#" title="title_a2"><img src="http://dev.adokikaku.com/wp-content/uploads/2015/04/sample_a2.jpg" alt="title_a2" width="300" /></a></li>
			<li class="item"><a href="#" title="title_a3"><img src="http://dev.adokikaku.com/wp-content/uploads/2015/04/sample_a3.jpg" alt="title_a3" width="300" /></a></li>
			<li class="item"><a href="#" title="title_a4"><img src="http://dev.adokikaku.com/wp-content/uploads/2015/04/sample_a4.jpg" alt="title_a4" width="300" /></a></li>
			<li class="item"><a href="#" title="title_a5"><img src="http://dev.adokikaku.com/wp-content/uploads/2015/04/sample_a5.jpg" alt="title_a5" width="300" /></a></li>
		</ul>
</div>

<div class="image_item">
		<ul class="image_items">
			<li class="item"><a href="#" title="title_b1"><img src="http://dev.adokikaku.com/wp-content/uploads/2015/04/sample_b1.jpg" alt="title_b1" width="300" /></a></li>
			<li class="item"><a href="#" title="title_b2"><img src="http://dev.adokikaku.com/wp-content/uploads/2015/04/sample_b2.jpg" alt="title_b2" width="300" /></a></li>
			<li class="item"><a href="#" title="title_b3"><img src="http://dev.adokikaku.com/wp-content/uploads/2015/04/sample_b3.jpg" alt="title_b3" width="300" /></a></li>
			<li class="item"><a href="#" title="title_b4"><img src="http://dev.adokikaku.com/wp-content/uploads/2015/04/sample_b4.jpg" alt="title_b4" width="300" /></a></li>
			<li class="item"><a href="#" title="title_b5"><img src="http://dev.adokikaku.com/wp-content/uploads/2015/04/sample_b5.jpg" alt="title_b5" width="300" /></a></li>
		</ul>
</div>

 


<style>

div.image_item{display:inline-block; margin:1em;}

ul.image_items{
	display:block;
	overflow:hidden;
	width:300px;
	height:200px;
}
ul.image_items,
ul.image_items > li.item{
	margin:0;
	padding:0;
}

</style>


この後、表示領域の画像が入れ替わるようにJavaScriptのコードを記述していく。

JavaScriptのコード

表示領域(ul.images)の画像が入れ替わるように、次の様な処理のスクリプトを記述していく。

  • 1)マウスカーソルが表示領域(ul.images)にある あるいは 表示領域をタップしている間、
  • 2)現在のリストの最初の要素を最後にもってくる。
  • 3)前項(2)の処理を定期的に繰り返す。
  • 4)マウスが表示領域を外れた場合 あるいは 他の部分をタップした場合は、「2」の処理を中断する。


まず(3)の繰り返し処理には setInterval を使用するが、このタイマー用のグローバル変数を用意しておく。

<script>
var image_item_timer;


リストの画像は(非表示部分も含めて)ブラウザに全部読ませてから処理をさせたいので、 $(window).load に仕掛ける。


$(window).load(function(){


※ 画像の数が増える様であれば、(1)の後にajax通信を追加して…など改良の余地はある。

1)マウスカーソルが表示領域(ul.images)にある あるいは 表示領域をタップしている間

jQueryのイベントハンドラ「on」に touchstart mouseenter を指定することで、マウスカーソルが乗っている状態 あるいは タップを開始した時のイベントを指定する事ができる。

	$("ul.image_items").on("touchstart mouseenter",function(){ …


既に稼働しているタイマーがある場合は、 clearInterval でタイマーを明示的にリセット(停止)させる。 つまり、2つ以上同時に処理中になる事が無いようにする。


		if(image_item_timer && image_item_timer != "undefined"){
			clearInterval(image_item_timer);
		}

2)現在のリストの最初の要素を最後にもってくる

リストの画像が2件以上ない場合は処理させたくないので、li.itemの数で絞り込む。


		if($(this).find("li").length > 1){


この後、setInterval の指定をしていくが、タイマーを設定中は $(this) で対象の ul.images を指定する事ができなくて不便なので、$(this) を変数 target に控えておく(ここでもハマった)。


			var target = $(this);

3)前項(2)の処理を定期的に繰り返す

グローバル変数のタイマーに「リストの最初の要素を最後にもってくる」処理を記述する。
実際には、リストの最初の要素のコピーをとり削除、取得したコピーをリストの末尾に追加する処理を行う。

JavaScriptでのコピーは基本的に参照渡しになる? ようなので、明示的にクローンコピーを作成することに注意する。


			image_item_timer = setInterval(function() {
			
				//先頭要素のクローン(コピー)を作成
				var clone = target.find("li").first().clone(true);
				
				//先頭要素を削除
				target.find("li").first().remove();
				
				//作成したクローンを最後に追加
				clone.clone(true).insertAfter(target.find("li").last());


ちなみに target.find("li").first() でなく、target.find("li").get(0) や target.find("li:first- child") とでは返ってくるオブジェクトが異なる様で、remove等のメソッドがありませんエラーが多発してハマったところである。


処理の間隔を1/1000ミリ秒で指定する。


			}, 1000); //end setInterval
			
		}

4)マウスが表示領域を外れた場合 あるいは 他の部分をタップした場合は、(2)の処理を中断する。

jQueryのイベントハンドラ「on」に touchstart mouseleave を指定して、マウスカーソルが表示領域外に出た場合 あるいは 他の部分をタップした時に、グローバル変数のタイマーを clearInterval する処理を記述する。

タップの場合は、タップした場所が画像の表示領域でない場合にタイマー停止処理を仕掛けるので、マウスの mouseleave 場合とは別立てで記述した。


	//マウスカーソルが離脱したら停止(PC用)
	$("ul.image_items").on("mouseleave",function(){
		if(image_item_timer && image_item_timer != "undefined"){
			clearInterval(image_item_timer);
		}
	});
	
	//画面のどこかをタップしたら停止(スマホ・タブレット用)
	$("body").on("touchstart",function(){
		if($(this).parents(".image_item").length == 0){
			if(image_item_timer && image_item_timer != "undefined"){
				clearInterval(image_item_timer);
			}
		}
	});
});

>/script<

ひととおりのJavaScriptソースコード


>script<
//タイマーはグローバル変数で管理
var image_item_timer;

//画像が読み込まれてから仕掛けたいので、$(window).loadに
$(window).load(function(){
	
	//ターゲットにマウスが乗ったら(mouseenter)又はタップしたら(touchstart)開始
	$("ul.image_items").on("touchstart mouseenter",function(){
		//とりあえず処理中のものがあったらタイマー停止
		if(image_item_timer && image_item_timer != "undefined"){
			clearInterval(image_item_timer);
		}

		if($(this).find("li").length > 1){
			//setIntervalの処理コードでは $(this) が使えない(中身が変わってしまう)ので控えておく
			var target = $(this);
			
			//タイマー設定
			image_item_timer = setInterval(function() {
				//先頭要素のクローン(コピー)を作成
				var clone = target.find("li").first().clone(true);
				//先頭要素を削除
				target.find("li").first().remove();
				//作成したクローンを最後に追加
				clone.clone(true).insertAfter(target.find("li").last());
			}, 1000); //end setInterval
			
		}
	});
	
	//マウスカーソルが離脱したら停止(PC用)
	$("ul.image_items").on("mouseleave",function(){
		if(image_item_timer && image_item_timer != "undefined"){
			clearInterval(image_item_timer);
		}
	});
	
	//画面のどこかをタップしたら停止(スマホ・タブレット用)
	$("body").on("touchstart",function(){
		if($(this).parents(".image_item").length == 0){
			if(image_item_timer && image_item_timer != "undefined"){
				clearInterval(image_item_timer);
			}
		}
	});
});
>/script<