前回の記事で、iPhoneやiPad、Androidなどに加えてPCでも動作する
フリック/スワイプ動作UIをjQueryで実装する方法を紹介しましたが、
前回の単純なフリック/スワイプのUI動作に加えて、
自動で次の画像に切り替わるスライドショー動作と
メインビジュアル部分にNEXT/BACKのボタンを追加したパターンでの
画像ギャラリーを作ってみたので紹介してみたいと思います。
jQueryでフリック/スワイプ動作付きの自動再生スライドショーを作成する実験
まずは動作サンプルから。
一定の間隔で自動で次の画像に切り替わります。
画像の切り替えはサムネイルクリックの他、メインビジュアル部分の左右にあるNEXT/BACKボタンと
メインビジュアル部分をフリック/スワイプすることで切り替えることが可能になっています。
メインビジュアル部分にマウスオーバーしている間(フリック/スワイプ動作の間)は
自動再生機能は停止します。
この動作の全体構成について、
HTMLから。
◆HTML <div id="flickscroll"> <ul> <li><img src="img/photo01.jpg" width="400" height="400" alt="" /></li> <li><img src="img/photo02.jpg" width="400" height="400" alt="" /></li> <li><img src="img/photo03.jpg" width="400" height="400" alt="" /></li> <li><img src="img/photo04.jpg" width="400" height="400" alt="" /></li> </ul> </div><!--/#flickscroll--> <div id="flickthumb"> <ul> <li><img src="img/photo01.jpg" width="100" height="100" alt="" /></li> <li><img src="img/photo02.jpg" width="100" height="100" alt="" /></li> <li><img src="img/photo03.jpg" width="100" height="100" alt="" /></li> <li><img src="img/photo04.jpg" width="100" height="100" alt="" /></li> </ul> </div><!--/#flickthumb-->
HTMLは前回の記事の内容と同じです。
上部の<div id=”flickscroll”>がメイン部分にあたるソースになり、
下部の<div id=”flickthumb”>がサムネイル部分になります。
2つの<div>の中にはそれぞれにリストを入れ込みます。(ID名は変更可能)
HTMLはメイン用とサムネイル用の<div>と<ul>リストを用意するのみです。
リストの数はいくつでも増減可能です。
そしてこのHTMLソースに対してのCSSは以下の様に。
◆CSS /* #flickscroll --------------------------- */ #flickscroll { margin: 0 auto; width: 400px; height: 400px; text-align: left; position: relative; } #flickscroll ul { top: 0; left: 0; height: 400px; position: absolute; overflow: hidden; } #flickscroll ul li { width: 400px; height: 400px; float: left; display: inline; overflow: hidden; } #flickscroll #moveprev { top: 0; left: -30px; width: 30px; height: 400px; background: transparent url(../img/moveprev.jpg) no-repeat left top; position: absolute; cursor: pointer; } #flickscroll #movenext { top: 0; right: -30px; width: 30px; height: 400px; background: transparent url(../img/movenext.jpg) no-repeat left top; position: absolute; cursor: pointer; } /* #flickthumb --------------------------- */ #flickthumb { margin: 10px auto; width: 400px; height: 100px; text-align: center; } #flickthumb ul { width: 400px; height: 100px; } #flickthumb ul li { width: 100px; height: 100px; float: left; cursor: pointer; display: inline; } #flickthumb ul li.active { filter:alpha(opacity=100)!important; -moz-opacity: 1!important; opacity: 1!important; } /* ======================================= ClearFixElements ======================================= */ #flickscroll ul:after, #flickthumb ul:after { content: "."; height: 0; clear: both; display: block; visibility: hidden; } #flickscroll ul, #flickthumb ul { display: inline-block; overflow: hidden; }
CSSも前回の内容とさほど変わりませんが
NEXT/BACKボタンを形成するセレクタを追加してあります。
実際のフリック/スワイプ動作させる箇所「#flickscroll」で
全体の幅と高さの表示サイズを指定しています。
全体を囲うID「#flickscroll」の中に入る
リスト<ul>は「position:absolute」で絶対位置にして、
幅widthは<li>の数によってスクリプト側で計算して入れるので
ここでは指定しないようにしています。
サムネイル箇所についてはとくにスクリプト動作事態には影響しないレイアウト調整のみになっています。
そして実際に動作を実行させるスクリプトは以下の様になります。
◆SCRIPT <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <script type="text/javascript"> $(function(){ var $setMainId = $('#flickscroll'); var $setThumbId = $('#flickthumb'); var scrollSpeed = 300; var delayTime = 5000; var mainWidth = parseInt($setMainId.css('width')),mainHeight = parseInt($setMainId.css('height')); $setMainId.wrapInner('<div id="flickmask"></div>'); var $setMaskId = $('#flickmask'); $setMaskId.css({width:(mainWidth),height:(mainHeight),position:'relative',overflow:'hidden',cursor:'pointer'}); var $setMaskUl = $setMaskId.children('ul'), $setThumbUl = $setThumbId.children('ul'), $setThumbLi = $setThumbUl.children('li'), $setThumbLiFirst = $setThumbUl.children('li:first'), $setThumbLiLast = $setThumbUl.children('li:last'), listWidth = parseInt($setMaskUl.children('li').css('width')), listCount = $setMaskUl.children('li').length, leftMax = -((listWidth)*((listCount)-1)); $setMaskUl.each(function(){ $(this).css({width:(listWidth)*(listCount)}); }); var isTouch = ('ontouchstart' in window); $setMaskUl.bind( {'touchstart mousedown': function(e){ var $setMaskUlNot = $setMaskId.children('ul:not(:animated)'); $setMaskUlNot.each(function(){ e.preventDefault(); this.pageX = (isTouch ? event.changedTouches[0].pageX : e.pageX); this.leftBegin = parseInt($(this).css('left')); this.left = parseInt($(this).css('left')); this.touched = true; clearInterval(setTimer); }); },'touchmove mousemove': function(e){ if(!this.touched){ return; } e.preventDefault(); this.left = this.left - (this.pageX - (isTouch ? event.changedTouches[0].pageX : e.pageX) ); this.pageX = (isTouch ? event.changedTouches[0].pageX : e.pageX); if(this.left < 0 && this.left > leftMax){ $(this).css({left:this.left}); } else if(this.left >= 0) { $(this).css({left:'0'}); } else if(this.left <= leftMax) { $(this).css({left:(leftMax)}); } },'touchend mouseup mouseout': function(e){ if (!this.touched) { return; } this.touched = false; var $setThumbLiActive = $setThumbUl.children('li.active'); if(this.leftBegin > this.left && (!((this.leftBegin) === (leftMax)))){ $(this).stop().animate({left:((this.leftBegin)-(listWidth))},scrollSpeed); $setThumbLiActive.each(function(){ $(this).removeClass('active'); $(this).next().addClass('active'); }); } else if(this.leftBegin < this.left && (!((this.leftBegin) === 0))) { $(this).stop().animate({left:((this.leftBegin)+(listWidth))},scrollSpeed); $setThumbLiActive.each(function(){ $(this).removeClass('active'); $(this).prev().addClass('active'); }); } else if(this.leftBegin === 0) { $(this).css({left:'0'}); } else if(this.leftBegin <= leftMax) { $(this).css({left:(leftMax)}); } slideTimer(); } }); $setThumbLi.click(function(){ clearInterval(setTimer); var connectCont = $setThumbLi.index(this); $setMaskUl.stop().animate({left:(-(listWidth)*(connectCont))},scrollSpeed,function(){ slideTimer(); }); $setThumbLi.removeClass('active'); $(this).addClass('active'); }); $setThumbLiFirst.addClass('active'); $setThumbLi.css({opacity:'0.5'}); $setMainId.append('<div id="moveprev"></div><div id="movenext"></div>'); var $setPrevId = $('#moveprev'); var $setNextId = $('#movenext'); var $setPrevNextId = $('#movenext,#moveprev'); $setPrevNextId.css({opacity:'0.5'}); $setNextId.click(function(){ var $setThumbLiActive = $setThumbUl.children('li.active'); $setThumbLiActive.each(function(){ var listLengh = $setThumbLi.length; var listIndex = $setThumbLi.index(this); var listCount = listIndex+1; if(listLengh == listCount){ $setThumbLiFirst.click(); } else { $(this).next('li').click(); } }); }); $setPrevId.click(function(){ var $setThumbLiActive = $setThumbUl.children('li.active'); $setThumbLiActive.each(function(){ var listLengh = $setThumbLi.length; var listIndex = $setThumbLi.index(this); var listCount = listIndex+1; if(1 == listCount){ $setThumbLiLast.click(); } else { $(this).prev('li').click(); } }); }); slideTimer(); function slideTimer() { setTimer = setInterval(function(){ var $setThumbLiActive = $setThumbUl.children('li.active'); $setThumbLiActive.each(function(){ var listLengh = $setThumbLi.length; var listIndex = $setThumbLi.index(this); var listCount = listIndex+1; if(listLengh == listCount){ $setThumbLiFirst.click(); } else { $(this).next('li').click(); } }); },delayTime); }; var agent = navigator.userAgent; if(!(agent.search(/iPhone/) != -1 || agent.search(/iPad/) != -1 || agent.search(/iPod/) != -1 || agent.search(/Android/) != -1)){ $setThumbLi.hover(function(){ $(this).stop().animate({opacity:'1'},300); },function(){ $(this).stop().animate({opacity:'0.5'},300); }); $setPrevNextId.hover(function(){ $(this).stop().animate({opacity:'1'},300); },function(){ $(this).stop().animate({opacity:'0.5'},300); }); } }); </script>
メイン部分の<div>要素の幅と高さの値を元に
フリック/スワイプ動作でスライドさせる<ul>の幅やスライドさせる距離など計算しています。
スクリプト開始部分にある
————————————————
var $setMainId = $(‘#flickscroll’);
var $setThumbId = $(‘#flickthumb’);
var scrollSpeed = 300;
var delayTime = 5000;
————————————————
は上から
————————————————
・該当するメインエリアのID名
・該当するサムネイルエリアのID名
・フリック/スワイプ動作でスライドさせた時のスライドスピード
・次の画像に切り替わるまでの待機時間
————————————————
となっているので、
値を変更することでカスタマイズが可能です。
スクリプトも少々作りが荒いところもあり、
もう少し簡略化したかったのですが
今のところこれくらいが限界かと。。
前回の記事の応用で実験的に作ってみたフリック/スワイプ動作付きのスライドショーですが
この様な画像スライドギャラリーが必要な際のご参考に是非。。