以前からjQueryを使ってのシンプルなスライドショーをいくつか紹介していますが
やはり今後はサイト上に設置するスライドショー関連も
レスポンシブに対応している必要が出てくることは必至なので
試しに作ってみたのを紹介してみます。
jQueryでレスポンシブ対応のサムネイル付きクロスフェードスライドショーを作る方法
今回のレスポンシブ動作はブラウザ枠を目いっぱいにするタイプなので
まずは別枠表示で動作サンプルから。。
「jQueryでレスポンシブ対応のサムネイル付きクロスフェードスライドショーを作る方法」サンプルを別枠で表示
サンプルでは6枚の画像を自動でクロスフェードで切り替え、
下に並べてあるサムネイルをクリックすることでも
メインビジュアル部分を切り替えることができる形になっています。
(左右のNEXT/BACK透過ボタンで画像を切り替えることも可。)
サンプルでは最大幅を「800px」最小幅を「320px」として
ブラウザ幅によってスライドショー部分が拡大縮小します。(どちらの値も変更可)
簡単な動作仕様については以上になります。
全体構成についてまずはHTMLから。
◆HTML <div class="slideShow"> <div class="mainView"> <ul> <li><a href="#1"><img src="img/photo1.jpg" alt=""></a></li> <li><a href="#2"><img src="img/photo2.jpg" alt=""></a></li> <li><a href="#3"><img src="img/photo3.jpg" alt=""></a></li> <li><a href="#4"><img src="img/photo4.jpg" alt=""></a></li> <li><a href="#5"><img src="img/photo5.jpg" alt=""></a></li> <li><a href="#6"><img src="img/photo6.jpg" alt=""></a></li> </ul> </div><!--/.mainView--> <div class="thumbNail"> <ul> <li><img src="img/photo1.jpg" alt=""></li> <li><img src="img/photo2.jpg" alt=""></li> <li><img src="img/photo3.jpg" alt=""></li> <li><img src="img/photo4.jpg" alt=""></li> <li><img src="img/photo5.jpg" alt=""></li> <li><img src="img/photo6.jpg" alt=""></li> </ul> </div><!--/.thumbNail--> </div><!--/.slideShow-->
クラスやIDを付けた全体を囲う任意のブロック要素「.slideShow」の中に
メインビジュアル部分のブロック要素「.mainView」と
サムネイル部分のブロック要素「.thumbNail」を配置し
それぞれの中に<ul>リストを使って画像を並べます。
(メインビジュアルの画像は<a>タグで囲ってありますが
リンクする必要がない場合はこのタグは不要です。)
サンプルでは画像を6つにしていますが
これを増減させるには単純に<li>の数をそれぞれ同じ個数増減するだけです。
ページネーションや左右のNEXT/BACKボタンは
スクリプト側から生成するようにしているので
HTMLには記述しません。
そしてCSSは以下の様になります。
◆CSS /* .slideShow ------------------------- */ .slideShow { margin: 0 auto; text-align: left; display: none; } /* .mainView ------------------------- */ .slideShow .mainView { width: 100%; position: relative; overflow: hidden; } .slideShow .mainView ul { width: 100%; overflow: hidden; position: relative; } .slideShow .mainView ul li { top: 0; left: 0; width: 100%; position: absolute; } .slideShow .mainView ul li img { width: 100%; } /* .thumbNail ------------------------- */ .slideShow .thumbNail { width: 100%; overflow: hidden; } .slideShow .thumbNail ul { width: 110%; } .slideShow .thumbNail ul li { float: left; display: inline; overflow: hidden; cursor: pointer; } .slideShow .thumbNail ul li img { width: 100%; } .slideShow .thumbNail ul li.active { filter: alpha(opacity=100)!important; -moz-opacity: 1!important; opacity: 1!important; } /* sideNavi ------------------------- */ .slideShow .mainView .btnPrev, .slideShow .mainView .btnNext { top: 0; width: 5%; height: 100%; position: absolute; z-index: 100; } .slideShow .mainView .btnPrev { left: 0; background: #ccc url(../img/btnPrev.png) no-repeat center center; } .slideShow .mainView .btnNext { right: 0; background: #ccc url(../img/btnNext.png) no-repeat center center; } /* ======================================= ClearFixElements ======================================= */ .slideShow ul:after { content: "."; height: 0; clear: both; display: block; visibility: hidden; } .slideShow ul { display: inline-block; overflow: hidden; }
スライドショー部分の幅や高さは
スクリプト側から制御するので
CSS側では幅100%だけ入れておきます。
ブラウザ幅の判別などもスクリプト側で制御するので
CSSでのメディアクエリー指定も特に使用しておりません。
(実際にページに組み込む際にはページのレイアウト制御等々で使用することになると思いますが)
スライド左右の透過NEXT/BACKボタン部分の
色など見た目はCSSで指定しておきます。
そして実際の動作スクリプトは以下の様になります。
◆SCRIPT <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script> $(function(){ $(window).load(function(){ var setWrap = $('.slideShow'), setMainView = $('.mainView'), setThumbNail = $('.thumbNail'), setMaxWidth = 800, setMinWidth = 320, thumbNum = 6, thumbOpc = 0.5, fadeTime = 1000, delayTime = 5000, sideNavi = 'on', // 'on' or 'off' autoPlay = 'on'; // 'on' or 'off' setWrap.each(function(){ var thisObj = $(this), childMain = thisObj.find(setMainView),mainUl = childMain.find('ul'),mainLi = mainUl.find('li'),mainLiFst = mainUl.find('li:first'), childThumb = thisObj.find(setThumbNail),thumbUl = childThumb.find('ul'),thumbLi = childThumb.find('li'),thumbLiFst = childThumb.find('li:first'),thumbLiLst = childThumb.find('li:last'); thisObj.css({width:setMaxWidth,display:'block'}); mainLi.each(function(i){ $(this).attr('class','view' + (i + 1).toString()).css({zIndex:'98',opacity:'0'}); mainLiFst.css({zIndex:'99'}).stop().animate({opacity:'1'},fadeTime); }); thumbLi.click(function(){ if(autoPlay == 'on'){clearInterval(setTimer);} var connectCont = thumbLi.index(this); var showCont = connectCont+1; mainUl.find('.view' + (showCont)).siblings().stop().animate({opacity:'0'},fadeTime,function(){$(this).css({zIndex:'98'});}); mainUl.find('.view' + (showCont)).stop().animate({opacity:'1'},fadeTime,function(){$(this).css({zIndex:'99'});}); $(this).addClass('active'); $(this).siblings().removeClass('active'); if(autoPlay == 'on'){timer();} }); thumbLi.css({opacity:thumbOpc}); thumbLiFst.addClass('active'); // メイン画像をベースにエリアの幅と高さを設定 var mainLiImg = mainLi.find('img'), baseWidth = mainLiImg.width(), baseHeight = mainLiImg.height(); // レスポンシブ動作メイン imgSize(); function imgSize(){ var windowWidth = parseInt($(window).width()); if(windowWidth >= setMaxWidth) { thisObj.css({width:setMaxWidth}); childMain.css({width:baseWidth,height:baseHeight}); mainUl.css({width:baseWidth,height:baseHeight}); mainLi.css({width:baseWidth,height:baseHeight}); thumbLi.css({width:((setMaxWidth)/(thumbNum))}); } else if(windowWidth < setMaxWidth) { if(windowWidth >= setMinWidth) { thisObj.css({width:'100%'}); childMain.css({width:'100%'}); mainUl.css({width:'100%'}); mainLi.css({width:'100%'}); } else if(windowWidth < setMinWidth) { thisObj.css({width:setMinWidth}); childMain.css({width:setMinWidth}); mainUl.css({width:setMinWidth}); mainLi.css({width:setMinWidth}); } var reHeight = mainLiImg.height(); childMain.css({height:reHeight}); mainUl.css({height:reHeight}); mainLi.css({height:reHeight}); var reWidth = setThumbNail.width(); thumbLi.css({width:((reWidth)/(thumbNum))}); } } $(window).resize(function(){imgSize();}); imgSize(); // サムネイルマウスオーバー var agent = navigator.userAgent; if(!(agent.search(/iPhone/) != -1 || agent.search(/iPad/) != -1 || agent.search(/iPod/) != -1 || agent.search(/Android/) != -1)){ thumbLi.hover(function(){ $(this).stop().animate({opacity:'1'},200); },function(){ $(this).stop().animate({opacity:thumbOpc},200); }); } // ボタン移動動作 function switchNext(){ var setActive = thumbUl.find('.active'); setActive.each(function(){ var listLengh = thumbLi.length, listIndex = thumbLi.index(this), listCount = listIndex+1; if(listLengh == listCount){ thumbLiFst.click(); } else { $(this).next('li').click(); } }); } function switchPrev(){ var setActive = thumbUl.find('.active'); setActive.each(function(){ var listLengh = thumbLi.length, listIndex = thumbLi.index(this), listCount = listIndex+1; if(1 == listCount){ thumbLiLst.click(); } else { $(this).prev('li').click(); } }); } // サイドナビボタン(有り無し) if(sideNavi == 'on'){ childMain.append('<a href="javascript:void(0);" class="btnPrev"></a><a href="javascript:void(0);" class="btnNext"></a>'); var btnPrev = thisObj.find('.btnPrev'),btnNext = thisObj.find('.btnNext'),btnPrevNext = thisObj.find('.btnPrev,.btnNext'); if(!(agent.search(/iPhone/) != -1 || agent.search(/iPad/) != -1 || agent.search(/iPod/) != -1 || agent.search(/Android/) != -1)){ btnPrevNext.css({opacity:thumbOpc}).hover(function(){ $(this).stop().animate({opacity:'0.9'},200); },function(){ $(this).stop().animate({opacity:thumbOpc},200); }); } else { btnPrevNext.css({opacity:thumbOpc}); } btnPrev.click(function(){switchPrev();}); btnNext.click(function(){switchNext();}); } // 自動再生(有り無し) if(autoPlay == 'on'){ function timer(){ setTimer = setInterval(function(){ switchNext(); },delayTime); } timer(); } }); }); }); </script>
スクリプト開始部分にある設定値の内容は以下の様になっています。
var setWrap = $(‘.slideShow’) | スライドショー全体を囲うブロック要素名(IDでも可) |
---|---|
setMainView = $(‘.mainView’) | メインビジュアル部分を囲うブロック要素名(IDでも可) |
setThumbNail = $(‘.thumbNail’) | サムネイル部分を囲うブロック要素名(IDでも可) |
setMaxWidth = 800 | スライドショー部分の最大幅 |
setMinWidth = 320 | スライドショー部分の最小幅 |
thumbNum = 6 | 一行に並べるサムネイル数 |
thumbOpc = 0.5 | サムネイルの非アクティブ時の透過度 |
fadeTime = 1000 | フェードアニメーションスピード |
delayTime = 5000 | スライドアニメーション待機時間 |
sideNavi = ‘on’ | 左右NEXT/BACKの表示/非表示(非表示の場合は「off」等) |
autoPlay = ‘on’ | 自動切換え動作のON/OFF(自動切換えさせない場合は「off」等) |
これらの設定値を変更することでもろもろ調整が可能になっています。
スクリプト全体はあまりシンプルと言える構成ではありませんが
少しの設定値を調整するだけで簡単に設置することは可能になっているかと思います。
画像サイズ(比率)によって各エリアの幅と高さを取得して制御していることもあり
使用する(切り替える)画像は全て幅と高さを同サイズのものを使用する必要があります。
サンプルではサムネイルを1行に6つ全て並べていますが
「thumbNum = 6」を「3」とすることで1行に3つ並べて2行にわたって表示する形になります。
「sideNavi = ‘on’」を「off」とすれば左右のボタンは表示されなくなります。
(記述は「off」でなくても「on」じゃなければ何でもいいです・・・)
1ページ内に複数設置する場合は自動スライド機能は一つ目のスライダーのみにしか動作しないので
必要なければ「autoPlay = ‘on’」を「off」としていただければと思います。
(こちらも記述は「off」でなくても「on」じゃなければ何でもいいです・・・)
左右のボタン非表示、サムネイル3個2行表示、自動切換え動作を止めたパターンのサンプルを別枠で表示
今回のサンプルではフリック動作は未実装です。(フリックスライドパターンは後日紹介予定)
iPhoneやAndroid端末でも動作するハズ。
レスポンシブ対応のサムネイル付きクロスフェードスライドショーを実装する際にぜひ。。。