スマートフォン:flipsnap(5)

バグ取りには時間がかかります…。
前回の最後で紹介した画像がずれるバグですが、結果から言うとcssで簡単に対処できました。
※デバッグしやすいように一定時間でページが切り替わる処理は外しています。

デバッグ用サンプル
サンプル:18_flipsnap.html  ここで利用しているcssはこちら
※jQueryのソースはhtmlに書いてあります。

 
flipsnap.jsのコードを調べて、フリックの位置がcurrentXで管理されていることを
確認したので、currentXがどのようにずれるのかを調べました。
以下のjQueryを追加してタッチ後のcurrentXを確認するようにしていました。

$(document).on("touchend mouseup",function(){
 var myX = flipsnap.currentX;
 $(".debug").text(myX);
})

しかしバグが発生した状態でもcurrentXは正常の値を表示しており問題はありませんでした。
ここで早速手詰まりになったのですが、PCで動作確認中に表示されていた横スクロールを
移動してcurrentXを表示させたのです。すると見た目はずれているのにcurrentXは正常の
値となり、バグと同じ現象ではないか!となったのです。

 
つまりスマートフォンでは横スクロールは見えていなくても、操作が可能で希に操作されてしまう
ことでバグが発生していたのだと。ということで#showcaseのcssにoverflow:hidden;を
設定しスクロールバーを表示しないようにしました。

#showcase {
 width: 100%;
 position:relative;
 overflow:hidden;
}

そしたらバグは発生しないようになりました。めでたし、めでたし。
 
 
 

スマートフォン:flipsnap(4)

今回は一定時間ごとにページを切り替えるようにします。ポイントなのは
タッチしている間はページを切り替えないようにする点です。
 
 

一定時間ごとにページを切り替える

一定時間ごとにページを切り替えるにはjavaScriptのsetIntervalを利用します。
このサンプルはタッチ中にもページが切り替わってしまいます。そしてタッチ中に
ページが切り替わると画像がずれるバグとなります…。

一定時間ごとにページを切り替える
サンプル:16_flipsnap.html  ここで利用しているcssはこちら
※jQueryのソースはhtmlに書いてあります。

 
注意点は以下のjQueryです。三項演算子を利用して次のページが最大ページを
越えていたら最初のページに移動し、そうでなければ次のページに移動します。
変数maxPageはjQueryの最初の部分で設定しています。

function changeFunc() {
 maxPage < flipsnap.currentPoint+1 ? flipsnap.moveToPoint(0) : flipsnap.toNext();
}
setInterval(changeFunc,5000);

 
 
 

タッチ中はページを切り替えないようにする

16_flipsnap.htmlはタッチ中にページが切り替わると画像がずれるバグがでます。
ですので、flicksimple.jsのようにタッチ中はページが切り替わらないように
しました。

タッチ中はページを切替えない
サンプル:17_flipsnap.html  ここで利用しているcssはこちら
※jQueryのソースはhtmlに書いてあります。

 
flipsnapではタッチ中というフラグがないので、それはjQueryで補います。
以下の様にイベントハンドラを設定し、タッチ中はtouchFlgをtrueにします。

$("#showcase").on("touchstart mousedown" ,function(){touchFlg = true});
$("#showcase").on("touchend touchcancel mouseup" ,function(){touchFlg = false});

そして、ページ切り替えの際にtouchFlgがtrueだったら切り替えをしないようにします。

function changeFunc() {
 if ( touchFlg ) return;//----タッチ中であれば処理しない
 maxPage < flipsnap.currentPoint+1 ? flipsnap.moveToPoint(0) : flipsnap.toNext();
}

 
 
 

バグがでたよ〜〜

17_flipsnap.htmlはAndroidでもlockされないので、非常に実用的だと思うのですが
いろいろ動作確認をしていたら、バグを見つけました...。
縦スクロールとフリックが同時に発生するような動作(斜めの動き)で画像が
ずれることがあるのです...。Androidでは縦スクロールとフリックが同時に発生する
事はないようなのでバグは出せませんでした。

 
むむぅ。次回以降で何とか修正に挑戦したいと思います。
 
 
 

スマートフォン:flipsnap(3)

flicksimpleもステキだとは思うのですが、縦スクロールのロックがどうしても気になって
しまいます…。ですがflipsnap.jsではAndroidでも縦スクロールしているので、再度
flipsnap.jsに着目し、これを発展させてflicksimple.jpと同じようなことが
できるようにしたいと思います。
 
 

全幅対応:レイアウトが変わったら再設定をする

これまで紹介したflipsnapのサンプルでは指定したエリア内で画像を切り替えます。
まずは、これをブラウザの全幅を利用した仕様に変更しましょう。
全幅にするためにjavaScriptを追加する必要はありません。flicksimpleの
サンプルと同じようにCSSで設定しています。
 
ここで注意しなければいけないのが、縦向き/横向きにレイアウトを変更した際の
処理についてです。具体的に言うと、レイアウトが変わった際に初期化しないと
計算が合わなくなり、正常に機能しないのです。
 
しかし、flipsnapには初期化のためのrefreshというメソッドが搭載されており
これを実行すればブラウザの幅に合わせて再設定できます。これで問題が解決できます。

next/prevボタンの追加
サンプル:14_flipsnap.html  ここで利用しているcssはこちら
※jQueryのソースはhtmlに書いてあります。

 
ポイントとなるjQueryは以下の部分です。flipsnapではflicksimpleと異なり
独自のイベントを持っていないので、代わりにjQueryのresizeイベントを利用して
ブラウザのサイズが変わったらリフレッシュ(再設定)します。
これで全幅にしても問題なくレイアウト変更に対応できます。

$(window).resize(function(){
 flipsnap.refresh();
})

 
 
 

ブラウザの幅に合わせて画像を拡大する

続いてブラウザの幅に合わせて画像を拡大するようにしました。これもjQueryの
resizeイベントを利用します。

next/prevボタンの追加
サンプル:15_flipsnap.html  ここで利用しているcssはこちら
※jQueryのソースはhtmlに書いてあります。

 
以下の様に再設定の処理に画像のサイズ変更の処理を追加しています。また
最初に一度、resizeFuncを実行するようにしました。これを実行しないと最初は
cssの設定通りの画像サイズになるため、横レイアウトで起動した際に画像が大きく
ならないからです。

$(window).resize(resizeFunc);				
function resizeFunc() {
 var myWidth = $(document).width();
 myImage.css("width", myWidth);
 myImage.css("height", myWidth*0.5625);
 flipsnap.refresh();
}
※myImageはjQueryの最初の方で設定している画像のセレクタです

これで横レイアウトにしたときに画像が拡大されるようになりました。しかも
flicksimple.jsと異なりAndroidでも縦スクロールできます。
 
次回は一定時間でページを切り替えるようにします。
 
 
 

スマートフォン:flicksimple(5)

flicksimpleは前回で終わりにしようと思ったのですが、今回もflicksimpleにしました。
 

ブラウザの幅に合わせて画像を拡大縮小

横レイアウトにしたときに画像をブラウザ幅に合わせて拡大するサンプルを作成しました。
以下のキャプチャのように画像が横レイアウトで画像が拡大されていることが確認できます。
 

ブラウザ幅に合わせて画像を拡大
サンプル:13_flicksimple.html  ここで利用しているcssはこちら
※web-kit系のPCブラウザでも確認できます。jQueryのソースはhtmlに書いてあります。

 
flicksimpleはレイアウトが変わったときにonResizeイベントが発生するので、そのイベントが
発生したらブラウザ幅に合わせて画像をリサイズしています。画像までのセレクタが長いので
最初に画像のオブジェクトをmyImageに代入しておきます。
onResizeイベントの設定はonChangeの方法と同じです。画像の高さを設定している部分にある
数値0.5625は、今回利用している画像のアスペクト比(180/320)です。

var myImage = $("#showcase>ul>li>a>img");

settingObj.onResize = function () {
 var myWidth = $(document).width();
 myImage.css("width", myWidth);
 myImage.css("height", myWidth*0.5625);
}

 
以前にflicksimpleで向きを変更すると、なんだかぎこちないと愚痴りましたが
これは、きちんと変更が完了してから設定を再設定しているためなのですね。
おかげで画像のサイズが変更された後でも正しい位置に表示されます。
 
 

注意点

Androidではフリックエリア上で縦スクロールが一切できないので(lockプロパティが効かない)
画像サイズを大きくしてshowcaseだけで画面を覆ってしまうと、非常に困った自体になります。
ですので今回サンプルとして作成しましたが、この設定は避けた方がよいのかもしれません。
 
 

Androidでのlockを外してみた

flipsnap.jsではAndroiddえもスクロールできるので、flicksimple.jsでも
できそうな気がします。ということでflicksimple.jsでAndroidを無条件に
lockしている部分を探して修正してみました…。
flicksimple.jsの278行目に以下の様なコードがあります。ここで無条件に
androidの場合はスクロールできないようにしています。

if ( o.android || o.lock ) {
 e.preventDefault();
}

ということで、ここでandroidの条件を外したのですが…。そうしたら
フリックの動作が非常に悪くなりました。雰囲気的にはブラウザの縦スクロールと
jQueryの横スクロールが同時にできない感じで、純粋にどちらか一方の操作を
しないと機能しないといった感じです。
だからAndroidは無条件にlockされているのですね…。
 
でも、これは何とかしたいなぁ…。
 
 
 

スマートフォン:flicksimple(4)

今回はflicksimpleのポインタをクリックしたら該当するページに移動するようにしたり
一定時間ごとにページを切り替えるようにします。
 

ポインタをクリックして該当ページに移動する

ポインタクリックの追加
サンプル:11_flicksimple.html  ここで利用しているcssはこちら
※web-kit系のPCブラウザでも確認できます。jQueryのソースはhtmlに書いてあります。

 
ページ移動の際に利用するnextPage,prevPageメソッドを前回紹介しました。
ポインタのクリックは、これと似たメソッドを利用することで実装できます。
そのメソッドは以下のgoToメソッドで引数に移動先のページ番号を設定するだけです。
ポインタのidの取得方法はflipsnap.jsと全く同じです。

$("#interface .pointer span").click(function() {
 var clickID = Number(this.id);
 fsObj.goTo(clickID);//----指定したページに移動します。
});

 
 

一定時間でページを切り替える

最後に一定時間でページを切り替えるようにします。一定時間ごとに処理を実行するのは
javascriptのsetIntervalを利用しますが、そこに設定するfunction内にテクニックが
あります。

一定時間ごとにページを切替る
サンプル:12_flicksimple.html  ここで利用しているcssはこちら
※web-kit系のPCブラウザでも確認できます。jQueryのソースはhtmlに書いてあります。

 
setIntervalで実行するfunctionは以下の様になっています。

function changeFunc() {
 if ( fsObj.startX !== null ) return;
 fsObj.pageLength < fsObj.page+1 ? fsObj.goTo(1) : fsObj.nextPage();
}

まずポイントなのがfunction内1行目のif文の処理です。startXプロパティはタッチした
座標を取得するものなのですが、タッチされていない場合はnullを返します。
つまり、ここで何をしているかというと、タッチされている場合は何もしないでreturnする
つまりタッチ中にページが切り替わることを防いでいるのです。
次の行は3こう演算子を利用して最後のページだったら1ページに戻るようにし、そうでない
場合は次のページに移動するようにしています。
 
 
 

まとめ

flicksimpleはブラウザの全幅を利用したフリックにも対応し、さらに縦スクロールや
商品が2行になった複雑な配置にも対応しています。またタッチを検出できるので
タッチ中は自動で切り替わらないなど配慮することもできるので、とても実用的と感じました。
 
おしまい
 
 
 

スマートフォン:flicksimple(3)

今回はflicksimpleにインターフェイスを付けていこうと思います。
 

インジケーターの表示

まずは現在のページを表示するインジケーターを追加します。今回はクリックした位置に移動する
機能は付けません。

インジケーターの追加
サンプル:09_flicksimple.html  ここで利用しているcssはこちら
※web-kit系のPCブラウザでも確認できます。jQueryのソースはhtmlに書いてあります。

 
flipsnap.jpと同じようにflicksimple.jsもコールバック関数を設定できるので、
移動が完了したら特定の処理を実行するようにします。但しコールバックの登録の仕方が
flipsnap.jpと異なり以下の様になります。前回の07b_flicksimple.htmlの所で
紹介したようにflicksimple設定用のオブジェクトで設定します。

settingObj = new Object();//---設定用Object
//---ページが切り替わった際の処理を追加
settingObj.onChange = function () {
 myPointer.filter('.current').removeClass('current');
 myPointer.eq(this.page-1).addClass('current');
}

flicksimple.jsはページが切り替わるとonChangeイベントが実行されます。ですので
上記のようにonChangeにfunctionを登録します。
 
イベント以外にポイントとして、現在表示しているページを取得するpageプロパティがあります。
上記のようにthisを伴い利用することで現在表示しているページ番号を取得できるので
これを利用してポインタの切り替えを行っています。
 
さらに注意点としてflipsnap.jpの際はポインタのidは0から開始しましたが
flicksimple.jsでは以下の様に1から開始していることに注意してください。

<span id="1" class="current"></span">
<span id="2""></span">
<span id="3""></span">
<span id="4""></span">
<span id="5""></span">

 
 
 

next/prevボタンの追加

続いてnext/prevボタンを追加します。

next/prevボタンの追加
サンプル:10_flicksimple.html  ここで利用しているcssはこちら
※web-kit系のPCブラウザでも確認できます。jQueryのソースはhtmlに書いてあります。

今回はflicksimpleオブジェクトにアクセスする必要があるので、まずは以下の様に
flicksimpleオブジェクトを取得します。下段のように最初のflicksimpleの実行と
同時に行うことはできないので気を付けましょう。

$("#showcase").flickSimple(settingObj);
var fsObj = $("#showcase").flickSimple();//---flickSimpleオブジェクトを取得
//---1行にまとめると機能しません...
var fsObj = $("#showcase").flickSimple(settingObj);

このように作成したflicksimpleオブジェクトに対しnextPage、prevPageメソッドを実行
することでページを切り替えることが可能です。

$("#interface .pointer .next").click(function() {
 fsObj.nextPage();//---次のページへ
});
$("#interface .pointer .prev").click(function() {
 fsObj.prevPage();//---前のページへ
});

 
今回はここまで、次回はインジケータのポイントをクリックしたら該当するページへ移動
するようにしたいと思います。
 
 
 

スマートフォン:flicksimple(2)

縦スクロールの禁止

前回の記事で気になった縦スクロールの件ですが、これはflicksimpleにオプションを
設定することで禁止し対処することが可能になります。まずは実際に縦スクロールを禁止
したサンプルを確認しましょう。htmlのjQueryの部分にコメントで解説があるので
記事と合わせて確認してください。

縦スクロールの禁止
サンプル:07b_flicksimple.html  ここで利用しているcssは07_flicksimple.htmlと同じです。
※スマートフォンで確認してください。jQueryのソースはhtmlに書いてあります。

 
flicksimpleにオプションを設定する方法は以下の様に、flicksimpleを設定する際に
引数としてObjectオブジェクトを渡します。オプションの設定は複数有り、それぞれ
Objectオブジェクトのプロパティとして設定します。
縦スクロールを禁止するのは以下の様にlockプロパティにtrueを設定します。

settingObj = new Object();//--flickSimpleを設定するオブジェクト作成
settingObj.lock = true;//---縦スクロールをロック
$("#showcase").flickSimple(settingObj);//---引数に設定オブジェクトを渡す

 
これでフリック中に縦スクロールしなくなるので、微妙な違和感が無くなります。
しかし横レイアウトにした場合、フリックエリアが画面全体を覆ってしまうと、縦スクロール
ができないため、ページスクロールできず困った自体になってしまいます。
これはスマートフォン:ショーケースの観察の記事で記した問題と同じです。
縦レイアウトで閲覧すればよいので、深刻な問題ではないのかもしれませんが
個人的には避けたい問題です…。
 
次回はページ位置を示すインジケータを付ける予定です。
 
 
 

スマートフォン:flicksimple(1)

今回からしばらくは、web designing2012年1月号の2番目に紹介されているflickSimple.js
を学んでいこうと思います。本紙だけでなく以下のページからサンプルとマニュアルを
確認できます。参考:jQuery.flickSimple.js
 
 

最小設定

まずはインジケータやnext/prev等のない最小限のサンプルで学んでいきます。
見た目はflipsnapと同じですが、ブラウザの全幅を利用して動作します。その際、画像だけではなく
指定した領域(サンプルでは#showcase)でフリックする事も可能です。

最小設定のflicksimple
サンプル:07_flicksimple.html  ここで利用しているcssはこちら
※web-kit系のPCブラウザでも確認できます。jQueryのソースはhtmlに書いてあります。

 
以下の様にflipsnap同様にとてもシンプルに導入できます。

$("#showcase").flickSimple();

 
 

flipsnapとの違い

flipsnapと操作感を比べて、操作感が少し異なったのでメモ。
フリックの途中で縦スクロールにも敏感に反応する。たとえば斜めにフリックすると
画像が横スクロールし、ブラウザ自体は縦スクロールします。
これは当たり前の使用に感じますが、すこしでも縦方向にフリックがあると縦に
スクロールしてしまうのは違和感がある気がします。
 
その点flipsnapでは少量の縦スクロールは無視するようになっているので
違和感はありません。なにげに凄い良くできた配慮だと思います。
とはいえ、flicksimpleにも何か凄い機能があるかもしれないので 
次回もflicksimpleについて学ぼうと思います。
 
 
 

Posted in jQuery, smart phone, study, study | スマートフォン:flicksimple(1) はコメントを受け付けていません

スマートフォン:flipsnap(2)

前回に引き続きflipsnap.jsの機能を学ぼうと思います。
 

next/prevボタン

flipsnap.jsではnext/prevボタンも簡単に追加することができます。
ややこしいページ管理も一切必要ありません。

next/prevボタンの追加
サンプル:05_flipsnap.html  ここで利用しているcssはこちら
※jQueryのソースはhtmlに書いてあります。

jQueryのポイントは以下の部分です。flipsnapオブジェクトに対してtoNextやtoPrevメソッドを
実行するだけで、ページの管理など必要なくインジケータと連携されます。

$("#showcase .pointer .next").click(function() {
 flipsnap.toNext();
});
$("#showcase .pointer .prev").click(function() {
 flipsnap.toPrev();
});

 
 
 

インジケーターをクリックできるようにする

flipsnap.jsは指定したページに移動する機能も用意されているので、インジケーターのポイントを
クリックしたら、該当するページに移動するようにもできます。タップしやすいようにインジケータは
若干大きく変更しました。

インジケータをクリックできるようにしたサンプル
サンプル:06_flipsnap.html  ここで利用しているcssはこちら
※jQueryのソースはhtmlに書いてあります。

 
ポイントとなるjQueryは以下の部分です。flipsnapオブジェクトに対してmoveToPointメソッドを
実行するだけです。移動先は引数として渡します。

$("#showcase .pointer span").click(function() {
 var clickID = Number(this.id);
 flipsnap.moveToPoint(clickID);
});

また今回の変更に対してインジケーターのポイント部分にも変更を加えました。どのポインターが
クリックされたか分かるようにidを割り当てています。0から開始するのがポイントです。

<span id="0" class="current"></span">
<span id="1""></span">
<span id="2""></span">
<span id="3""></span">
<span id="4""></span">

 
 

flipsnap.jsまとめ

ここまで確認してきたようにflipsnap.jsは非常にシンプルに導入できるのが大きなメリット
でしょう。またショーケースの観察で強調した通常のスクロールが阻害されない点もメリットです。
ですが、ブラウザの全幅にはまだ対応していないようです。
web designing2012年1月号の2番目に紹介されているflickSimple.jsはそれに対応している
ようなので、次回以降はそれを学ぼうと思います。
 
 
 

スマートフォン:flipsnap(1)

前回までのショーケースはフリックに対応していません。以前にiOS用のサンプルを作成しましたが
今では多くのプラグインがあるようなので、プラグインを利用してみようと思います。
参考:iOS+jQuery:部分横スクロール(2)
参考:iOS+jQuery:部分横スクロール(3)
 
 
 

flipsnap.jp

web designing 2012年1月号のjQueryLabで最初に紹介されているものです。
flipsnap.js ※これを作成したpxgridの方がweb designingの記事を執筆されています
 
これからいくつかサンプルを紹介しますが、非常にシンプルにフリックを導入することができます。
まずは最小限の設定だけをしたサンプルです。サンプルはweb-kit系のPCブラウザでも
確認できますが、ショーケースの外でマウスアップすると誤動作するようです。

最もシンプルな例
サンプル:03_flipsnap.html  ここで利用しているcssはこちら
※jQueryのソースはhtmlに書いてあります。

 
cssは非常にシンプルでjQueryに至っては以下のコードだけです。

Flipsnap("#showcase .flipsnap");

 
 
 

インジケーターの追加

全部で何枚の画像があり、現在どの画像を表示しているか確認できるようなインジケータを
設定することも観点にできます。但しインジケータをクリックすることはできません。

インジケータの追加
サンプル:04_flipsnap.html  ここで利用しているcssはこちら
※jQueryのソースはhtmlに書いてあります。

flipsnap.jsでは移動が完了したら実行するコールバック関数を設定できます。それを
利用することで移動後にインジケータのポイントを変更します。コールバックはaddEventListener
を利用し、追加するイベント名はflipsnap.moveendとなります。

flipsnap.element.addEventListener('flipsnap.moveend', function() {
 $("#showcase .pointer span").filter('.current').removeClass('current');
 $("#showcase .pointer span").eq(flipsnap.currentPoint).addClass('current');
}, false);

 
またインジケータの分、htmlにコードが追加してあることも確認してください。
インジケータのポインタはすべてcssで作成されていてステキです。
 
今回はここまでにしたいと思います。次回はnext/prevボタンを追加する予定です。