Titaniumでスクロール目盛により参照を切り替えるUI

Titanium mobileで[Weightbot](http://itunes.apple.com/app/weightbot-track-your-weight/id293642937?mt=8)のような横スクロール目盛を作ってみた。

主な機能
 1. スクロールラベルの区切りで参照するデータを切り替える
 2. 目盛の矢印がスクロールラベルの丁度真ん中に来るようにする

２番目の機能を実現するロジック
 ・ 貫性でスクロール中に速度が落ちたらちょうど真ん中に自動スクロール
 ・ 指を離して少し経っても動いていなかったらちょうど真ん中に自動スクロール

Titanium mobile SDK 1.8から"dragEnd"イベントが拾えるようになりやっと実現できました。

パラメータは感覚で適当に決めました。

ご意見、アドバイスいただけたら嬉しいです。

全く同じ内容ですが実行画面は[こちら](http://yonecode.blogspot.com/2012/02/titaniumui.html)で見れます。

```js:scrollCursor.js
var win = Ti.UI.currentWindow;

// 仮データ
var dataList = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];

// 参照データを表示するラベル
var dataLabel = Titanium.UI.createLabel({
	backgroundColor: 'black',
	borderRadius: 30,
	color:'white',
	font:{
		fontFamily:'Helvetica Neue',
		fontSize:100
	},
	textAlign:'center',
	top:50, left:'auto', height: 150, width: 200,
	text: dataList[0]
});
win.add(dataLabel);

// 目盛に合わせてスクロールさせることで参照データを切り替えるScrollView
var scrollView = Titanium.UI.createScrollView({
	contentWidth:'auto',
	contentHeight:'auto',
	top:290,
	height:70,
	width:320,
	backgroundColor:'#gray',
	zIndex:1
});

var labelNum = dataList.length + 1; // 切り替えラベルの数
var labelWidth = 50; // 切り替えラベルの横幅
for(var i = 0; i < labelNum; i++){
	if(i < labelNum - 1){
		// スクロールメモリのラベル
		var scrollLabel = Ti.UI.createLabel({
			borderColor:'black',
			backgroundColor:'#A0522D',
			height:70, width:labelWidth,
			left: 135 + labelWidth * i,
			font:{
				fontFamily:'Helvetica Neue',
				fontSize:25
			},
			textAlign: 'center',
			text:i
		});
		scrollView.add(scrollLabel);
	} else {
		// 選択範囲外は無地グレー
		var scrollLabel = Ti.UI.createLabel({
			backgroundColor:'#gray',
			height:70, width:135,
			left: 135 + labelWidth * i
		});
		scrollView.add(scrollLabel);
	}
}
win.add(scrollView);

// 目盛
var allow = Titanium.UI.createLabel({
	text:"▼",
	font:{fontSize:20},
	color:'#gray',
	top:200,
	left:150,
	width:20,
	textAlign:'center',
	zIndex:3
});
win.add(allow);


// ---------------------------ここからロジック部分---------------------------------

// 変数初期化
var pos_old = 0;
var time_old = new Date();
var catchDragEnd = false;
var throwDistance = 0;

// Titanium mobile SDK 1.8からdragEndイベントが拾えるようになった
scrollView.addEventListener('dragEnd', function(){
	catchDragEnd = true;

	// 0.2秒後にあまり動いていなければ切りの良い位置へ自動スクロール
	setTimeout(function(){
		if(pos_old % labelWidth != 0 && throwDistance < labelWidth / 2){
			scrollView.scrollTo(Math.round(pos_old / labelWidth) * labelWidth, 0);
			throwDistance = 0;
			catchDragEnd = false;
		}
	}, 200);
});

scrollView.addEventListener('scroll', function(e){
	var pos_new = e.x;

	// 目盛の計算
	var index = Math.floor((pos_new + labelWidth / 2) / labelWidth);

	dataLabel.text = dataList[index];

	time_new = new Date();
	var time_diff = time_new.getTime() - time_old.getTime();

	// あまりにも細かく見すぎても意味が無いので0.1秒間隔でチェック
	if( 100 < time_diff ){
		var pos_diff = Math.abs(pos_new - pos_old);

		// dragEndイベントを拾ってからのスクロール距離の合計
		if(catchDragEnd) {
			throwDistance += pos_diff;
		}

		// スクロール速度の計算
		velocity = Math.round(pos_diff / time_diff * 1000);

		// 0.2秒以上経過していない場合
		// かつ、速度が遅くなった場合
		if(time_diff < 200 && velocity < 20){

			// 中途半端な位置の場合
			if(pos_new % labelWidth != 0){
				// 切りの良い位置へ自動スクロール
				scrollView.scrollTo(Math.round(pos_new / labelWidth) * labelWidth, 0);
				catchDragEnd = false;
				throwDistance = 0;
			}
		}

		time_old = time_new;
		pos_old = pos_new;
	}
});
```