iPhoneやiPad、Androidといったスマートフォンやタブレット端末では
フリック/スワイプと呼ばれる指でスライドさせるUIが付き物になっています。
jQueryでもこのフリック/スワイプ動作を実装できるプラグインはたくさんありますが
いざ自分で作ろうとすると意外と大変な動作だったりします。
この動作についていろいろ調べていたところ
Sleipnirのフェンリルさんのデベロッパーズブログにて、
iPhone/Android/PC 対応。jQuery で書くタッチイベント (フェンリル | デベロッパーズブログ)
と題した、jQueryでiPhoneやAndroid、PCでタッチイベントを取得する方法がとても参考になったので
この記事を参考にしてフリック/スワイプで操作するシンプルな画像ギャラリーを作ってみました。
jQueryでフリック/スワイプ動作の画像スライドギャラリーを作成する実験
まずは動作サンプルから。
下記の画像をフリック/スワイプしてみてください。
※PCのマウス操作でも動作します。
拡大画像部分を左右にフリック/スワイプすることで
画像が一枚一枚スライドします。
この動作の全体構成について、
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-->
上部の<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; overflow: hidden; cursor: pointer; } #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; } /* #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; }
実際のフリック/スワイプ動作させる箇所「#flickscroll」で
全体の幅と高さの表示サイズを指定しています。
全体を囲うID「#flickscroll」の中に入る
リスト<ul>は「position:absolute」で絶対位置にして、
幅widthは<li>の数によってスクリプト側で計算して入れるので
ここでは指定しないようにしています。
サムネイル箇所「#flickthumb」については
とくにスクリプト動作には影響しないレイアウト調整のみになっています。
そして実際に動作を実行させるスクリプトは以下の様になります。
◆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 $setMainUl = $setMainId.children('ul'), $setThumbUl = $setThumbId.children('ul'), $setThumbLi = $setThumbUl.children('li'), $setThumbLiFirst = $setThumbUl.children('li:first'), listWidth = parseInt($setMainUl.children('li').css('width')), listCount = $setMainUl.children('li').length, leftMax = -((listWidth)*((listCount)-1)); $setMainUl.each(function(){ $(this).css({width:(listWidth)*(listCount)}); }); var isTouch = ('ontouchstart' in window); $setMainUl.bind( {'touchstart mousedown': function(e){ var $setMainUlNot = $setMainId.children('ul:not(:animated)'); $setMainUlNot.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; }); },'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)}); } } }); $setThumbLi.click(function(){ var connectCont = $setThumbLi.index(this); $setMainUl.stop().animate({left:(-(listWidth)*(connectCont))},scrollSpeed); $setThumbLi.removeClass('active'); $(this).addClass('active'); }); $setThumbLiFirst.addClass('active'); $setThumbLi.css({opacity:'0.5'}); 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); }); } }); </script>
メイン部分の<div>要素の幅と高さの値を元に
フリック/スワイプ動作でスライドさせる<ul>の幅やスライドさせる距離など計算しています。
スクリプト開始部分にある
————————————————
var $setMainId = $(‘#flickscroll’);
var $setThumbId = $(‘#flickthumb’);
var scrollSpeed = 300;
————————————————
は上から
————————————————
・該当するメインエリアのID名
・該当するサムネイルエリアのID名
・フリック/スワイプ動作でスライドさせた時のスライドスピード
————————————————
となっているので、
値を変更することでカスタマイズが可能です。
メインエリア(画像)部分のアクションで
————————————————
・タッチした時
・タッチしたまま移動している時
・タッチが離れた時
————————————————
の3点でのそれぞれの値を見て
処理を加えてあります。
この3点での値を取得する方法が分かれば
画像ギャラリーのみでなく、いろいろなフリック/スワイプ操作での
UIが実装できるように感じています。
サンプルの動作環境は
・Windows
IE6,7,8
Forefox
Google Chrome
Safari
・Mac
Firefox
Safari
・iPhone
・iPad/iPad2
・Android
以上の動作で確認済みです。
jQueryでフリック/スワイプ動作のスライドギャラリーを作成する際に是非。。