jQuery(JavaScript)でタップ中・オンマウス中に画像を順次切り替える(PC・スマホ・タブレット対応)
動画共有サイト等によくある、画像にマウスを乗せている間、順次画像が切り替わるスクリプトを作成してみた。
ハマりにハマって、最終的には思ったとおりの挙動にする事ができたが、実際にはどんなコードで動いているのかは調べていないので…。
実際の挙動:画像を順次切り替える
次の様なものを作成する方法を紹介していく。
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<
