プラグインを使わずに、jQuery を使って簡単なスライドショーを行う方法のメモ。
そのページにアクセスすると自動的にスライドショーを行う単純なもの。
HTML
<div id="mainphoto"> <img src="images/photos/slideshow/P1030380.jpg" width="680" height="452" alt="photo title1"> <p id="title">photo title1</p> </div><!-- end of #mainphoto --> <div id="photolist"> <ul> <li>P1030380.jpg, photo title1</li> <li>P1030411.jpg, photo title2</li> <li>P1030429.jpg, photo title3</li> <li>P1030440.jpg, photo title4</li> <li>P1030447.jpg, photo title5</li> <li>P1030459.jpg, photo title6</li> <li>P1030600.jpg, photo title7</li> <li>P1030630.jpg, photo title8</li> <li>P1030664.jpg, photo title9</li> <li>P1030694.jpg, photo title10</li> <li>P1030819.jpg, photo title11</li> <li>P1030858.jpg, photo title12</li> </ul> </div><!-- end of #photolist -->
img 要素は絶対配置(position:absolute)を指定。
CSS
div#mainphoto { float: left; width: 680px; height: 452px; padding: 0; margin: 0; position: relative; } /*---img 要素---*/ div#mainphoto img { position: absolute; top: 0; left: 0; } /*---写真のタイトルを表示する p 要素---*/ div#mainphoto p#title { position: absolute; z-index: 10; bottom: 10px; right: 30px; font-size: 11px; font-size: 1.1rem; color: #FFF; } /*---表示する写真の情報を記述しておく div 要素---*/ div#photolist { display: none; }
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script> jQuery(function($){ var nextphoto = 1; function showphoto() { var photolist$ = $('div#photolist li'); var photocount = photolist$.length; var info = $(photolist$.get(nextphoto)).text().split(','); var src = $.trim(info[0]); var alt = $.trim(info[1]); var nextimg = '<img src="images/photos/slideshow/' + src + '" width="680" height="452" alt="' + alt + '">'; $('div#mainphoto p#title').fadeOut(300); $('div#mainphoto img').before(nextimg); $('div#mainphoto img:last').fadeOut(1000, function(){ $(this).remove(); $('div#mainphoto p#title').text(alt).fadeIn(200); }); nextphoto ++; if(nextphoto == photocount ) nextphoto = 0; } var timer = window.setInterval(showphoto, 3000); $(window).unload(function(){ window.clearInterval(timer); }); }); </script>
クロスフェードの代わりに animate() を使ってスライドさせて表示させる。
HTML は同じ。
CSS ではメインの画像の領域に「overflow: hidden;」を追加。その他は同じ。
CSS
div#mainphoto { float: left; width: 680px; height: 452px; padding: 0; margin: 0; position: relative; overflow: hidden; }
jQuery
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script> jQuery(function($){ var nextphoto = 1; function showphoto() { var photolist$ = $('div#photolist li'); var photocount = photolist$.length; var info = $(photolist$.get(nextphoto)).text().split(','); var src = $.trim(info[0]); var alt = $.trim(info[1]); var nextimg = '<img src="images/photos/slideshow/' + src + '" width="680" height="452" alt="' + alt + '">'; $('div#mainphoto p#title').fadeOut(300); $('div#mainphoto img').before(nextimg); //この部分を変更 $('div#mainphoto img:last').stop().animate({ marginLeft: '-680px' }, 600, function(){ $(this).remove(); $('div#mainphoto p#title').text(alt).fadeIn(200); }); nextphoto ++; if(nextphoto == photocount ) nextphoto = 0; } var timer = window.setInterval(showphoto, 3000); $(window).unload(function(){ window.clearInterval(timer); }); }); </script>
サンプル1-2では、元の画像がスライドして、その下に新しい画像が表示されるが、以下は新しい画像がスライドして上に表示される例。
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script> jQuery(function($){ var nextphoto = 1; function showphoto() { var photolist$ = $('div#photolist li'); var photocount = photolist$.length; var info = $(photolist$.get(nextphoto)).text().split(','); var src = $.trim(info[0]); var alt = $.trim(info[1]); var nextimg = '<img src="images/photos/slideshow/' + src + '" width="680" height="452" alt="' + alt + '">'; $('div#mainphoto p#title').fadeOut(300); //この部分を変更 var new_img$ = $(nextimg).css('left', '680px'); new_img$.insertAfter('#mainphoto img').animate({ left: 0 }, 600, function() { $('#mainphoto img:first').remove(); $('div#mainphoto p#title').text(alt).fadeIn(200); }); nextphoto ++; if(nextphoto == photocount ) nextphoto = 0; } var timer = window.setInterval(showphoto, 3000); $(window).unload(function(){ window.clearInterval(timer); }); }); </script>
カルーセルパネルの作り方を参考に、2枚の写真を一緒にスライドさせてみる。
今までのサンプルとは構造が異なるので HTML、CSS ともに新たに作成。
HTML
<div id="slider_wrap"> <div id="slider"> <div id="slider_inner"> <ul id="photo_list"> <li><a href="#"><img src="images/1.jpg" alt=""></a></li> <li><a href="#"><img src="images/2.jpg" alt=""></a></li> <li><a href="#"><img src="images/3.jpg" alt=""></a></li> <li><a href="#"><img src="images/4.jpg" alt=""></a></li> <li><a href="#"><img src="images/5.jpg" alt=""></a></li> <li><a href="#"><img src="images/6.jpg" alt=""></a></li> <li><a href="#"><img src="images/7.jpg" alt=""></a></li> <li><a href="#"><img src="images/8.jpg" alt=""></a></li> <li><a href="#"><img src="images/9.jpg" alt=""></a></li> <li><a href="#"><img src="images/10.jpg" alt=""></a></li> <li><a href="#"><img src="images/11.jpg" alt=""></a></li> <li><a href="#"><img src="images/12.jpg" alt=""></a></li> </ul> </div><!-- end of #slider_inner --> </div><!-- end of #slider --> </div><!-- end of #slider_wrap -->
CSS
#slider_wrap { margin: 20px auto; width: 720px; height: 423px; padding: 20px; background: #EFEFEF; position: relative; border: 1px solid #CCC; } #slider { width: 100%; height: 100%; overflow: hidden; } #photo_list { /*width: 640px; 幅は指定しない*/ height: 383px; padding: 20px; list-style-type: none; float: left; background: #999; } #photo_list li { float: left; margin-right: 20px; display: inline; } #photo_list img { border: none; }
jQuery では、setInterval を使って「slider_inner」を画像1つ分左にずらし、先頭の画像を最後に付け替える。
関連ページ:「カルーセルパネル(スライドパネル)の表示」
jQuery
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script> jQuery(function($){ var photo_list$ = $('#photo_list'); var li$ = $('#photo_list li'); //写真の数 var li_count = li$.length; //li 要素の幅 + その左右マージン var li_width = li$.width() + parseInt(li$.css('margin-left'), 10) + parseInt(li$.css('margin-right'), 10); //ul 要素の左右パディング var ul_padding = parseInt(photo_list$.css('padding-left') , 10) + parseInt(photo_list$.css('padding-right') , 10); var slider_inner$ = $('#slider_inner'); //slider_innerの幅を設定(li 要素の幅 * その個数 + パディング) slider_inner$.css('width', (li_width * li_count + ul_padding) + 'px'); //最後の li 要素を最初の位置へ $('#photo_list li:last').prependTo(photo_list$); //最後の li 要素を最初の位置へ移動した分ずらす slider_inner$.css('margin-left', '-' + li_width + 'px'); var timer = setInterval(function(){ slider_inner$.stop().animate({ marginLeft: parseInt(slider_inner$.css('margin-left'), 10) - li_width + 'px' }, 800, function(){ slider_inner$.css('margin-left', '-' + li_width + 'px'); $('#photo_list li:first').appendTo(photo_list$); }); },2500); }); </script>
写真がある程度の数になった場合、毎回最初の写真から表示しなおすのも何なので、このページに戻った場合、前回表示した写真から表示するようにする方法。
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script src="jquery.cookie.js"></script> <script> jQuery(function($){ if(!$.cookie('nextimage')) { //クッキーが設定されていなければクッキー'nextimage'を設定 $.cookie('nextimage', 0, { path: '/' } ); } //変数 nextphoto(写真のインデックス) にクッキーの値を格納。 //クッキーが使えない場合(undefined)は「0」を代入。 var nextphoto = $.cookie('nextimage') ? $.cookie('nextimage') : 0; //写真の情報を記述した li 要素のラップ集合 var photolist$ = $('div#photolist li'); //写真の合計数( li 要素の数) var photocount = photolist$.length; var p_title$ = $('div#mainphoto p#title'); //div#photolist 内に記述した li 要素の「nextphoto」に対応するテキストを「info」に取得 var info = $(photolist$.get(nextphoto)).text().split(','); var src = 'images/photos/slideshow/' + $.trim(info[0]); var alt = $.trim(info[1]); //画像にパス(src)を指定 $('div#mainphoto img').attr('src', src); //タイトルに alt を指定 p_title$.text(alt); function showphoto() { nextphoto ++; if(nextphoto == photocount ) nextphoto = 0; $.cookie('nextimage', nextphoto, { path: '/' } ); //写真のインデックスをクッキーに登録 info = $(photolist$.get(nextphoto)).text().split(','); src = $.trim(info[0]); alt = $.trim(info[1]); console.log($.cookie('nextimage')); var nextimg = '<img src="images/photos/slideshow/' + src + '" width="680" height="452" alt="' + alt + '">'; p_title$.fadeOut(300); $('div#mainphoto img').before(nextimg); $('div#mainphoto img:last').fadeOut(1000, function(){ $(this).remove(); p_title$.text(alt).fadeIn(200); }); } var timer = window.setInterval(showphoto, 3000); $(window).unload(function(){ window.clearInterval(timer); }); }); </script>
「停止」ボタンや現在表示されている写真を示す画像を追加。
写真の数を表す画像は HTML に1つだけ記述しておき、jQuery で写真の数分追加する。
HTML
<div id="mainphoto"> <img src="images/photos/slideshow/P1030380.jpg" width="680" height="452" alt="photo title1"> <p id="title">photo title1</p> </div><!-- end of #mainphoto --> <!-- 写真の数を表す画像 --> <div id="icon"><a href="#"><img src="images/slider-icon.png" height="14" width="14"></a></div> <p id="stop">Stop</p><!-- 停止ボタン --> <div id="photolist"><!-- 写真情報のリスト(非表示) --> <ul> <li>P1030380.jpg, photo title1</li> <li>P1030411.jpg, photo title2</li> <li>P1030429.jpg, photo title3</li> <li>P1030440.jpg, photo title4</li> <li>P1030447.jpg, photo title5</li> <li>P1030459.jpg, photo title6</li> <li>P1030600.jpg, photo title7</li> <li>P1030630.jpg, photo title8</li> <li>P1030664.jpg, photo title9</li> <li>P1030694.jpg, photo title10</li> <li>P1030819.jpg, photo title11</li> <li>P1030858.jpg, photo title12</li> </ul> </div><!-- end of #photolist -->
CSS
div#mainphoto { width: 680px; height: 470px; padding: 0; margin: 0 auto; position: relative; } /*---img 要素---*/ div#mainphoto img { position: absolute; top: 0; left: 0; } /*---写真のタイトルを表示する p 要素---*/ div#mainphoto p#title { position: absolute; z-index: 10; bottom: -10px; right: 0; font-size: 14px; color: #EEE; } /*---表示する写真の情報を記述しておく div 要素---*/ div#photolist { display: none; } #stop { cursor: pointer; background: #666; color: #FFF; border: 1px solid #ccc; width: 50px; height: 2em; text-align: center; line-height: 2em; margin: -30px 0 20px 60px; } #stop.start { background: #eee; color: #666; border-color: #666; } #icon { padding-top: 10px; width: 30px; margin: 0 auto; } #icon a { padding: 8px; }
写真に対応する画像をクリックした際の処理では、すでに「停止」ボタンが押されていなければスライドショーを停止する。
また、スライドショーを停止した場合は「停止」ボタンに「start」というクラスを追加して、表示を変更する。
jQuery
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script> jQuery(function($){ var photolist$ = $('#photolist'); var photolist_li$ = $('#photolist li'); var photo_count = photolist_li$.length; //現在表示されている写真のインデックス(初期化) var current_photo = 0; var is_first = true; function showphoto() { //初回のみインデックスを増加(同じ写真がすでに表示されているため) if(is_first) { current_photo ++; is_first = false; } var info = $(photolist_li$.get(current_photo)).text().split(','); var src = $.trim(info[0]); var alt = $.trim(info[1]); var nextimg = '<img src="images/photos/slideshow/' + src + '" width="680" height="452" alt="' + alt + '">'; $('div#mainphoto p#title').fadeOut(100); $('div#mainphoto img').before(nextimg); $('div#mainphoto img:last').fadeOut(1000, function(){ $(this).remove(); $('div#mainphoto p#title').text(alt).fadeIn(100); }); setup(); current_photo ++; if(current_photo == photo_count ) current_photo = 0; } var icon_width = $('#icon').width(); //写真の数を表す画像は HTML に1つだけ記述してあるのでパネルの数分生成 if(photo_count > 1) { for(var i = 0; i < photo_count -1 ; i++) { $('#icon a:first').clone().appendTo('#icon'); } $('#icon').css('width', icon_width * photo_count); } var icon_imgs$ = $('#icon img'); var icon_links$ = $('#icon a'); //現在表示されている写真に対応する画像の背景を指定 $(icon_imgs$.get(current_photo)).attr('src', "images/slider-icon-selected.png"); var photo_img$ = $('#photo_list img'); //写真に対応する画像の title 属性にリストの情報を設定 icon_imgs$.each(function(index) { var info = $(photolist_li$.get(index)).text().split(','); var alt = $.trim(info[1]); $(this).attr('title', alt); }); //写真に対応する画像のソースを指定(現在表示されているものは別の画像を設定) function setup() { icon_imgs$.attr('src', "images/slider-icon.png"); $(icon_imgs$.get(current_photo)).attr('src', "images/slider-icon-selected.png"); } //写真に対応する画像をクリックした際の処理 icon_links$.click(function() { if(!is_stopped) { stop_slide(); } current_photo = icon_links$.index($(this)); setup(); showphoto(); }); //「停止」ボタンをクリックした際の処理 var stop$ = $('#stop'); stop$.click(function() { if(is_stopped) { start_slide(); stop$.removeClass('start'); }else{ stop_slide(); stop$.addClass('start'); } }); var timer; var is_stopped = false; //スライドショーを開始する関数 function start_slide() { timer = window.setInterval(showphoto, 3000); stop$.text('Stop'); stop$.removeClass('start'); is_stopped = false; } //スライドショーを停止する関数 function stop_slide() { window.clearInterval(timer); stop$.text('Start'); stop$.addClass('start'); is_stopped = true; } //スライドショーを開始 start_slide(); $(window).unload(function(){ window.clearInterval(timer); }); }); </script>
「進む」「戻る」ボタンを追加してみる。構造は「サンプル1-4」を元に作成。
HTML
<div id="slider_wrap"> <!-- 「戻る」ボタン --> <p id="slider_prev"><img src="images/slider-prev.png" height="30" width="20" alt="previous"></p> <!-- 「進む」ボタン --> <p id="slider_next"><img src="images/slider-next.png" height="30" width="20" alt="next"></p> <div id="slider"> <div id="slider_inner"> <ul id="photo_list"> <li><a href="#"><img src="images/1.jpg" alt=""></a></li> <li><a href="#"><img src="images/2.jpg" alt=""></a></li> <li><a href="#"><img src="images/3.jpg" alt=""></a></li> <li><a href="#"><img src="images/4.jpg" alt=""></a></li> <li><a href="#"><img src="images/5.jpg" alt=""></a></li> <li><a href="#"><img src="images/6.jpg" alt=""></a></li> <li><a href="#"><img src="images/7.jpg" alt=""></a></li> <li><a href="#"><img src="images/8.jpg" alt=""></a></li> <li><a href="#"><img src="images/9.jpg" alt=""></a></li> <li><a href="#"><img src="images/10.jpg" alt=""></a></li> <li><a href="#"><img src="images/11.jpg" alt=""></a></li> <li><a href="#"><img src="images/12.jpg" alt=""></a></li> </ul> </div><!-- end of #slider_inner --> </div><!-- end of #slider --> <div id="icon"><a href="#"><img src="images/slider-icon.png" height="14" width="14"></a></div> <div id="title"><p>title</p></div> <p id="stop">Stop</p> </div><!-- end of #slider_wrap -->
CSS
#slider_wrap { margin: 20px auto; width: 720px; height: 423px; padding: 20px 20px 80px 20px; background: #EFEFEF; position: relative; border: 1px solid #CCC; } #slider_prev { position: absolute; top: 205px; left: 10px; cursor: pointer; } #slider_next { position: absolute; top: 205px; right: 10px; cursor: pointer; } #slider { width: 100%; height: 100%; overflow: hidden; } #photo_list { /* 幅は指定しない */ height: 383px; padding: 20px; list-style-type: none; float: left; background: #999; } #photo_list li { float: left; margin-right: 20px; display: inline; } #photo_list img { border: none; } #stop { cursor: pointer; background: #666; color: #FFF; border: 1px solid #999; width: 50px; height: 2em; text-align: center; line-height: 2em; margin: -40px 0 0 0; } #stop.start { background: #ccc; color: #666; border-color: #aaa; } #icon { padding-top: 10px; width: 30px; margin: 0 auto; } #icon a { padding: 8px; } #title { padding-top: 15px; width: 200px; margin: 0 auto; } #title p { text-align: center; font-size:14px; color: #999; }
jQuery では、写真のスライドアニメーションの途中で「進む」「戻る」ボタンをクリックできないように非表示にし、写真の数を表す画像をクリックしても何もしない「return false」ようにする(アニメーションの途中でクリックされると、位置がずれてしまうため)。
また写真の数を表す画像をクリックした場合はどちらの方向に移動するかは、近いほうを選択するようにしてみた。
jQuery
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script> jQuery(function($){ var photo_list$ = $('#photo_list'); var li$ = $('#photo_list li'); var li_count = li$.length; //写真の数 //現在表示されている画像のインデックス(初期化) var current_image = 0; var icon_width = $('#icon').width(); //写真の数を表す画像は HTML に1つだけ記述してあるのでパネルの数分生成 if(li_count > 1) { for(var i = 0; i < li_count -1 ; i++) { $('#icon a:first').clone().appendTo('#icon'); } $('#icon').css('width', icon_width * li_count); } var icon_imgs = $('#icon img'); var icon_links = $('#icon a'); //現在表示されている写真に対応する画像の背景を指定 $(icon_imgs.get(current_image)).attr('src', "images/slider-icon-selected.png"); var photo_img$ = $('#photo_list img'); icon_imgs.each(function(index) { $(this).attr('title', $(photo_img$.get(index)).attr('alt')); }); //li 要素の幅 + その左右マージン var li_width = li$.width() + parseInt(li$.css('margin-left'), 10) + parseInt(li$.css('margin-right'), 10); //ul 要素の左右パディング var ul_padding = parseInt(photo_list$.css('padding-left') , 10) + parseInt(photo_list$.css('padding-right') , 10); var slider_inner$ = $('#slider_inner'); //slider_innerの幅を設定(li 要素の幅 * その個数 + パディング) slider_inner$.css('width', (li_width * li_count + ul_padding) + 'px'); //最後の li 要素を最初の位置へ $('#photo_list li:last').prependTo(photo_list$); //最後の li 要素を最初の位置へ移動した分ずらす slider_inner$.css('margin-left', '-' + li_width + 'px'); var prev_next$ = $('#slider_prev, #slider_next'); var default_speed = 700; //クリックイベントで使用する関数(画像をスライドさせるアニメーション) //アニメーション中かどうかのフラグ var is_animate = false; function animate_image(margin_left, option, speed, delta) { is_animate = true; if(speed) { var speed = speed; }else{ var speed = default_speed; } //「進む」「戻る」ボタンを非表示に(クリックされると位置がずれる可能性があるため) prev_next$.hide(); slider_inner$.stop().animate({ marginLeft: margin_left + 'px' }, speed, function(){ //「進む」「戻る」ボタンを表示 prev_next$.show(); switch(option) { case 1: //$('#slider_prev').click()の際の処理 $('#photo_list li:last').prependTo(photo_list$); break; case 2: //$('#slider_next').click()の際の処理 $('#photo_list li:first').appendTo(photo_list$); break; case 3: //icon_links.click( )の際の処理(特になし) break; case 4: //icon_links.click( )の際の処理 //移動した分の写真をリストの最後に追加 for(var i = 0; i < delta; i ++) { $('#photo_list li:first').appendTo(photo_list$); } break; default: break; } //全てに共通の処理 slider_inner$.css('margin-left', '-' + li_width + 'px'); is_animate = false; }); } //現在表示されているパネルに対応する画像を変更とボタンを表示する処理 function setup() { icon_imgs.attr('src', "images/slider-icon.png"); $(icon_imgs.get(current_image)).attr('src', "images/slider-icon-selected.png"); } function show_title() { $('#title p').text($(photo_img$.get(current_image)).attr('alt')); } show_title(); $('#slider_prev').click(function(){ if(!is_stopped) { stop_carousel(); } animate_image(parseInt(slider_inner$.css('margin-left'), 10) + li_width, 1); if(current_image > 0 ) { current_image --; }else{ current_image = li_count -1; } setup(); show_title() ; }); $('#slider_next').click(function(){ if(!is_stopped) { stop_carousel(); } animate_image(parseInt(slider_inner$.css('margin-left'), 10) - li_width, 2); current_image = (current_image + 1) % li_count; setup(); show_title(); }); icon_links.click(function(){ //画像をスライドさせるアニメーション中の場合は何もしない(位置がずれるため) if(is_animate) return false; //スライドショーが停止されていない場合は停止する if(!is_stopped) { stop_carousel(); } //クリックされた画像の title 属性を タイトルに $('#title p').text($(this).find('img').attr('title')); var this$ = $(this); //クリックされた画像のインデックスを取得 var icon_index = icon_links.index(this$); //現在の写真を示す画像のインデックスを取得 var current_icon_index; icon_imgs.each(function(n) { if($(this).attr('src') == "images/slider-icon-selected.png") { current_icon_index = n; } }); //インデックスの差分を取得 var delta = Math.abs(icon_index - current_icon_index); //逆方向への移動距離を算出するための値 var alpha = li_count - delta; //それぞれのインデックスを比較して処理を実行 //クリックされた画像のインデックスが現在選択状態の画像のインデックスより小さい場合 if(icon_index < current_icon_index){ //差分が写真の数の半分より大きい場合(どちら側へ移動するかを決めるため) if(delta > li_count / 2) { var margin_left = parseInt($('#slider_inner').css('margin-left'), 10) - li_width * alpha; animate_image( margin_left, 4, 1500, alpha); current_image -= delta; setup(); }else{ //移動する前に移動分の画像の位置を変更しておく for(var i = 0; i < delta; i ++) { $('#photo_list li:last').prependTo(photo_list$); } slider_inner$.css('margin-left', '-' + li_width * (delta +1) + 'px'); var margin_left = parseInt($('#slider_inner').css('margin-left'), 10) + li_width * delta; animate_image( margin_left, 3, 800, delta); current_image -= delta; setup(); } }else{ if(delta > li_count / 2) { //移動する前に移動分の画像の位置を変更しておく for(var i = 0; i < alpha; i ++) { $('#photo_list li:last').prependTo(photo_list$); } slider_inner$.css('margin-left', '-' + li_width * (alpha +1) + 'px'); var margin_left = parseInt($('#slider_inner').css('margin-left'), 10) + li_width * alpha; animate_image( margin_left, 3, 1500, alpha); current_image += delta; setup(); }else{ var margin_left = parseInt($('#slider_inner').css('margin-left'), 10) - li_width * delta; animate_image( margin_left, 4, 800, delta); current_image += delta; setup(); } } return false; }); function carousel() { animate_image(parseInt(slider_inner$.css('margin-left'), 10) - li_width, 2); current_image = (current_image + 1) % li_count; setup(); show_title(); } var timer; var is_stopped = false; var stop$ = $('#stop'); function start_carousel() { timer = setInterval(function(){ carousel(); },2500); stop$.text('Stop'); is_stopped = false; stop$.removeClass('start'); } function stop_carousel() { clearInterval(timer); stop$.text('Start'); is_stopped = true; stop$.addClass('start'); } stop$.click(function(){ if(is_stopped) { start_carousel(); }else{ stop_carousel(); } }); start_carousel(); $(window).unload(function(){ window.clearInterval(timer); }); }); </script>
スライドショーを自動で開始して、サムネイルのパネルもそれに連動してスライドするものを作成しようとしたが、時々ブラウザがハングアップする現象が発生する。
setInterval の代わりに setTimeout を使って再帰的に呼び出すようにしてもハングアップするので、原因は何か他にあると思うが、今は保留。
このサンプルはまだ不完全なものなので、ブラウザがハングアップする可能性があるので注意してください。(問題が発生しても保障できません。)あくまでも個人的な練習のようなもので将来何かいい方法が思いつけば作り直すためのものです(覚えていれば)。
サンプル5(注意!)ブラウザがハングアップする可能性があります。
jQuery
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script> jQuery(function($){ //パネルの総数 var panel_count = $('#slider_inner ul.panel').length; var slider_width = $('#slider_wrap').width(); //パネル全体を格納する div 要素の幅を「表示領域の横幅 X パネルの数」に設定 var slider_inner$ = $('#slider_inner'); slider_inner$.css('width', slider_width * panel_count + 'px'); //現在表示されているパネルのインデックス(初期化) var current_panel = 0; //どのパネルが表示されているかを示す画像を表示する領域の幅 var icon_width = $('#icon').width(); //どのパネルが表示されているかを示す画像要素のパス(src) var icon_path = $('#icon a:first img').attr('src'); //現在表示されているパネル示す画像要素のパス var icon_selected_path = 'images/slider-icon-selected.png'; //パネルの数を表す画像は HTML に1つだけ記述してあるのでパネルの数分追加生成 if(panel_count > 1) { for(var i = 0; i < panel_count -1 ; i++) { $('#icon a:first').clone().appendTo('#icon'); } //「panel_count」を使ってパネルの数を表す画像の領域の幅を設定 $('#icon').css('width', icon_width * panel_count); } //パネルの数を表す画像のラップ集合を「icon_imgs」に格納 var icon_imgs = $('#icon img'); //パネルの数を表す画像のリンクのラップ集合を「icon_links」に格納 var icon_links = $('#icon a'); //現在表示されているパネルに対応する画像を変更(異なる色にする) $(icon_imgs.get(current_panel)).attr('src', icon_selected_path); //「進む」「戻る」ボタン var prev_next$ = $('#slider_prev, #slider_next'); //スライドショーが停止しているかどうか var stop_slide = true; icon_links.click(function(){ //パネルをスライドさせるアニメーション中の場合は何もしない(位置がずれるため) if(is_animate) return false; //スライドショーを停止 stop_slideshow(); stop_slide = true; var this$ = $(this); //クリックされた画像のインデックスを取得 var icon_index = icon_links.index(this$); //現在のパネルを示す画像のインデックスを取得 var current_icon_index; icon_imgs.each(function(n) { if($(this).attr('src') == icon_selected_path) { current_icon_index = n; } }); //現在のパネルを示す画像のインデックスを更新 current_panel = icon_index; icon_setup(); //インデックスの差分を取得 var delta = Math.abs(icon_index - current_icon_index); //それぞれのインデックスを比較して処理を実行 if(icon_index < current_icon_index){ animate_panel(parseInt($('#slider_inner').css('margin-left'), 10) + slider_width * delta); }else{ animate_panel(parseInt($('#slider_inner').css('margin-left'), 10) - slider_width * delta); } return false; }); var photo_per_panel = $('ul#first li').length; var photolist$ = $('div#photolist li'); var p_title$ = $('div#mainphoto p#title'); var photocount = photolist$.length; var nextphoto = 1; var info; var src; var alt; var nextimg; var photo_link$ = $('ul.panel li a'); var selected_photo; var panel_pos =0; var timer; photo_link$.click(function(){ stop_slideshow(); selected_photo = photo_link$.index($(this)); info = $(photolist$.get(selected_photo)).text().split(','); src = $.trim(info[0]); alt = $.trim(info[1]); nextimg = '<img src="images/photos/slideshow/' + src + '" width="680" height="452" alt="' + alt + '">'; p_title$.fadeOut(300); $('div#mainphoto img').before(nextimg); $('div#mainphoto img:last').fadeOut(1000, function(){ $(this).remove(); p_title$.text(alt).fadeIn(200); }); panel_pos = Math.floor(selected_photo / photo_per_panel); nextphoto = (selected_photo + 1) % photocount; return false; }); var is_stopped = false; $('#stop').click(function(){ if(is_stopped) { timer = window.setInterval(function(){ console.log(timer); showphoto(); stop_slide = true; }, 3000); $(this).text('Stop'); is_stopped = false; var margin_left = parseInt($('#slider_inner').css('margin-left'), 10); animate_panel(margin_left + slider_width * (current_panel - panel_pos) ); current_panel = panel_pos; icon_setup() }else{ console.log(timer); window.clearInterval(timer); $(this).text('Start'); is_stopped = true; } }); $('#slider_prev').click(function(){ stop_slideshow(); if(current_panel > 0) { animate_panel(parseInt($('#slider_inner').css('margin-left'), 10) + slider_width); current_panel --; icon_setup(); }else{ animate_panel(parseInt($('#slider_inner').css('margin-left'), 10) - (slider_width * (panel_count -1))); current_panel = panel_count -1; icon_setup(); } }); $('#slider_next').click(function(){ if(stop_slide) { stop_slideshow(); } if(current_panel < panel_count - 1) { animate_panel(parseInt($('#slider_inner').css('margin-left'), 10) - slider_width); }else{ animate_panel(parseInt($('#slider_inner').css('margin-left'), 10) + (slider_width * (panel_count -1))); } current_panel = (current_panel + 1) % panel_count; icon_setup(); }); function showphoto() { stop_slide = true; photolist$ = $('div#photolist li'); info = $(photolist$.get(nextphoto)).text().split(','); src = $.trim(info[0]); alt = $.trim(info[1]); nextimg = '<img src="images/photos/slideshow/' + src + '" width="680" height="452" alt="' + alt + '">'; p_title$.fadeOut(300); $('div#mainphoto img').before(nextimg); $('div#mainphoto img:last').fadeOut(1000, function(){ $(this).remove(); p_title$.text(alt).fadeIn(200); }); nextphoto ++; if(nextphoto >= photocount ) nextphoto = 0; if(nextphoto % photo_per_panel == 1) { stop_slide = false; panel_pos = (panel_pos + 1) % panel_count; $('#slider_next').click(); } } function stop_slideshow() { if(!is_stopped) { console.log(timer); window.clearInterval(timer); $('#stop').text('Start'); is_stopped = true; } } //パネルをスライドさせるアニメーション var default_speed = 800; var is_animate = false; function animate_panel(margin_left, speed) { is_animate = true; if(speed) { var speed = speed; }else{ var speed = default_speed; } prev_next$.hide(); slider_inner$.stop().animate({ marginLeft: margin_left + 'px' }, speed, function(){ prev_next$.show(); is_animate = false; }); } //現在表示されているパネルに対応する画像を変更する処理 function icon_setup() { icon_imgs.attr('src', icon_path); $(icon_imgs.get(current_panel)).attr('src', icon_selected_path); } timer = window.setInterval(function(){ console.log(timer); showphoto(); stop_slide = true; }, 3000); $(window).unload(function(){ window.clearInterval(timer); }); }); </script>