Titanium™ Advent Calendar 2013の10日目です。
いい感じにスライドするカルーセルを作るためのTips
ScrollViewとScrollableViewって似てて紛らわしいですよね。
で、ここで突然問題です。
勢い良くスワイプしたらその分、ススーってスライドするけど、最後止まるときは、どれかのviewが画面に収まる形でパッと止めるには、どうすればいいのか?
ScrollableView
ScrollableViewを使うと、一枚一枚のviewが紙芝居のようにスクロールします。ですが、勢い良くスワイプしても1つとなりのViewに移動するだけで、パッと止まってしまいます。
ScrollView
ScrollViewを使うと、勢い良くスワイプしたらその分の距離スライドしてくれますが、そのまま慣性の法則で動くだけで、キリのいいところで止まってくれません。
うまくミックスしてイケてるカルーセルができないかな?
いいとこ取りするんだ!
色々と考えたところ、以下の方法で進めました。
- まず、ベースとしては、ScrollViewを作って、そこにView1,View2,View3…を乗せて行きます。
- これでは、ViewNにぴたりと止まる部分がないため、慣性の法則のまま、止まってしまいます。
- ここを以下にクリアするかぁぁ!!!!!!が、今回の話しのメインです。
ススーっと動いて、ぴたっと止める処理
ソースコードで説明します。
var carousel = Ti.createScrollView(); // スクロールイベント carousel.addEventListener('scroll',function(e){ scrollStatus(e); });
scrollイベントに、scrollStatus()という関数を仕込みます。
function scrollStatus(e){ // 今の位置からページ算出 var currentPage = parseInt((e.x + pageSize/2) / pageSize); // 減速中に位置調整 if(e.decelerating){ adjustPosition(e.x, pre_x); } // 前の座標を保存 pre_x = e.x; }
scrollイベントのプロパティにdeceleratingというのがあります。これは減速中かどうかを表すパラメータです。減速してない間(勢いよくスライドしている間)は位置調整しません。
// スクロール位置調整 function adjustPosition(x,pre_x){ // スクロール速度 var dx = Math.abs(x - pre_x); // 速度が落ちたら if(dx < 5){ // 移動 carousel.scrollTo((currentPage * pageSize),0); } }
位置調整処理の中身です。scrollToで表示したいページに移動します。
ポイント
苦労した点は、どうやったら滑らかに動いて止まってくれるか?でした。
最初作ったときは、完全に止まったときにscrollToさせていたのですが、ものすごく不自然な動きになったので、じゃあ、どういうタイミングでscrollToさせれば自然になるのか?
その答えが スライドの速度が遅くなった時 でした。
前の座標(pre_x)と現在地(x)から速度(dx)を算出して、規定値より少なくなれば、scrollToする、という処理にすることで、かなり滑らかになりました。
実際の動き
ソースコードだけじゃイメージ分からなーい!ですよね?
なんと「Petap」というアプリで実装しております。
一度DLして動き見てみてくださいー!