マップの拡大縮小や移動にマルチタッチは、どうよ?
ってな話があって…
何となくマルチタッチに対応…。
何となくざっくりソース…。
[EAGLView.h]
//--------------------------------------
- ( void )touchesBegan:( NSSet* )touches withEvent:( UIEvent* )event;
- ( void )touchesMoved:( NSSet* )touches withEvent:( UIEvent* )event;
- ( void )touchesEnded:( NSSet* )touches withEvent:( UIEvent* )event;
- ( void )touchesCancelled:( NSSet* )touches withEvent:( UIEvent* )event;
[EAGLView.m]
- ( id ) initWithCoder:( NSCoder* )coder
{
...
// ※マルチタッチに対応します。
self.multipleTouchEnabled = YES;
...
}
//******************************************************************************
// タッチ処理
//******************************************************************************
//**************************************
// Work
//**************************************
BOOL touchFlag; // タッチフラグ
CGPoint touchPoint; // タッチ位置
CGPoint touchMove; // タッチ移動量
//--------------------------------------
BOOL touchMultiFlag; // マルチタッチフラグ
BOOL touchMultiLock; // マルチタッチフラグ
CGPoint touchMultiCenter; // マルチタッチ中心位置
float touchMultiLength; // マルチタッチ距離
CGPoint touchMultiMove; // マルチタッチ移動量
float touchMultiRotate; // マルチタッチ回転量
//**************************************
// touchesMultiParameterGet
//**************************************
- ( void ) touchesMultiParameterGet:( NSSet* )touches
{
static float lengthBase, rotateBase;
static CGPoint centerBase;
CGPoint point0, point1, center;
float length, rotate, x, y;
UITouch *touch;
NSArray *array;
touch = [touches anyObject];
array = [touches allObjects];
point0 = [ [array objectAtIndex:0]locationInView: self];
point1 = [ [array objectAtIndex:1]locationInView: self];
x = point0.x - point1.x;
y = point0.y - point1.y;
length = sqrt( x * x + y * y );
center.x = x / 2 + point1.x;
center.y = y / 2 + point1.y;
rotate = atan2( y, x );
// 初期化
// ※『touchMultiFlag』で判断しているので注意
if( !touchMultiFlag )
{
lengthBase = length;
centerBase = center;
rotateBase = rotate;
touchFlag = FALSE;
touchMultiLock =
touchMultiFlag = TRUE;
}
touchMultiLength = length - lengthBase;
touchMultiCenter = center;
touchMultiRotate = rotate - rotateBase;
touchMultiMove.x = center.x - centerBase.x;
touchMultiMove.y = - center.y + centerBase.y;
printf( "l:%f - r:%f - mx:%f - my:%f\n", touchMultiLength, touchMultiRotate, touchMultiMove.x, touchMultiMove.y );
}
//**************************************
// touchesParameterGet
//**************************************
- ( void ) touchesParameterGet:( NSSet* )touches
{
static CGPoint pointBackup;
UITouch *touch = [touches anyObject];
// マルチタッチ起動のチェック
// ※『[touches count]>1』は、『UITouchPhaseBegan』だけでなく『UITouchPhaseMoved』中にも来ます。
// ※そのためフラグとの組み合わせて起動をチェックしています。
if( !touchMultiFlag && ( [touches count] > 1 ) )
{
[self touchesMultiParameterGet:touches];
// …何か処理…
}
// マルチタッチ処理
if( touchMultiFlag )
{
if( ( touch.phase == UITouchPhaseEnded ) || ( touch.phase == UITouchPhaseCancelled ) )
{
touchMultiLock =
touchMultiFlag = FALSE;
return;
}
if( [touches count] <= 1 )
{
touchMultiFlag = FALSE;
return;
}
[self touchesMultiParameterGet:touches];
// …何か処理…
return;
}
if( touchMultiLock )
return;
// シングルタッチ処理
touchPoint = [touch locationInView:self];
switch( touch.phase )
{
case UITouchPhaseBegan:
touchFlag = TRUE;
pointBackup = touchPoint;
// …何か処理…
break;
case UITouchPhaseEnded:
touchFlag = FALSE;
// …何か処理…
break;
default:
if( !touchFlag )
return;
break;
case UITouchPhaseCancelled:
touchFlag = FALSE;
return;
}
touchMove.x = touchPoint.x - pointBackup.x;
touchMove.y = -touchPoint.y + pointBackup.y;
printf( "mx:%f - my:%f\n", touchMove.x, touchMove.y );
// …何か処理…
}
//**************************************
// touchesBegan
//**************************************
- ( void ) touchesBegan:( NSSet* )touches withEvent:( UIEvent* )event
{
[self touchesParameterGet:touches];
}
//**************************************
// touchesMoved
//**************************************
- ( void ) touchesMoved:( NSSet* )touches withEvent:( UIEvent* )event
{
[self touchesParameterGet:touches];
}
//**************************************
// touchesEnded
//**************************************
- ( void ) touchesEnded:( NSSet* )touches withEvent:( UIEvent* )event
{
[self touchesParameterGet:touches];
}
//**************************************
// touchesCancelled
// ※電話の着信などの強制割り込み時に呼ばれます。
//**************************************
- ( void ) touchesCancelled:( NSSet* )touches withEvent:( UIEvent* )event;
{
[self touchesParameterGet:touches];
}
//******************************************************************************
// End
//******************************************************************************
※『touchMultiLock』は、タッチする指を二本から一本、一本から二本と変えた時に
初期情報を初期化したいので『touchMultiFlag = FALSE』にします。
このとき『touchMultiFlag = touchFlag = FALSE』の状態が発生します。
さらにタッチする時に『UITouchBegan』まで発生します。
この時『[touches count]<=1』でシングルタッチ処理に流れてしまいます。
『touchMultiLock』でシングルタッチ処理へ流れるのを回避します。
ちなみに二本指の移動は、『iPhoneシミュレーター』で
『option + shift + マウス』でできるそうだ。
こちらに書いてあって助かった…。
[iPhone] iPhone シュミレータでマルチタッチを平行に動かす方法
有難うございます…。
>if( [touches count] == [ [event touchesForView:self] count] )
で最後の指が離れたのをチェックしろってのもあるけど…
3Dエディタのようにウインドウが個別にあってそのウインドウ内の
表示を個別に拡大縮小するのなら必要なのかも?
…
多分、これには必要無いと思う…。
…
取り合えず、これでOK!
と思う一方で…
駄目かも…。
あんま調べてないんで…。(汗)
何かバグ見付けたら教えてください…。>誰か…
※シミュレータでしか動作を確認していないんで実機だと駄目かも…。(汗)
PS.
ちなみに、これを作った後に『iPhone OS Reference Library』の
『Touches』ってサンプル見たけど…
全く異なる方式なので参考にならん…。
一応こちらに何となくテストプログラムをアップしてみた…。
「touch.zip」をダウンロード
操作は、こんな感じ…。
■マウスドラッグ
・移動
■option + マウスドラッグ
・拡大縮小
・回転
■option + shift + マウスドラッグ
・移動
詳しくは、ソースを見てちょ…。
2010年2月16日追記----------------
実機で試して見たらバグバグだった…。(汗)
二本以上になったら「event」から情報を得ないと駄目!
って事がわかった…。
でソースの書き換え…。
//******************************************************************************
// タッチ処理
//******************************************************************************
//**************************************
// Work
//**************************************
extern float scale;
extern float rotate;
extern CGPoint position;
//--------------------------------------
#define PI 3.1415926535897932384626433832795
#define SCALE_RATE 120
#define MOVE_RATE 80
//--------------------------------------
BOOL touchFlag; // タッチフラグ
//--------------------------------------
BOOL touchSingleFlag; // シングルタッチフラグ
CGPoint touchSinglePoint; // シングルタッチ位置
CGPoint touchSingleMove; // シングルタッチ移動量
//--------------------------------------
BOOL touchMultiFlag; // マルチタッチフラグ
BOOL touchMultiLock; // マルチタッチロックフラグ
CGPoint touchMultiCenter; // マルチタッチ中心位置
float touchMultiLength; // マルチタッチ距離
CGPoint touchMultiMove; // マルチタッチ移動量
float touchMultiRotate; // マルチタッチ回転量
//**************************************
// touchesMultiParameterGet
//**************************************
- ( void ) touchesMultiParameterGet:( UIEvent* )event
{
static float lengthBase, rotateBase;
static CGPoint centerBase;
CGPoint point0, point1, center;
float length, rotate, x, y;
NSArray *array;
array = [[event touchesForView:self] allObjects];
point0 = [[array objectAtIndex:0]locationInView:self];
point1 = [[array objectAtIndex:1]locationInView:self];
x = point0.x - point1.x;
y = point0.y - point1.y;
length = sqrt( x * x + y * y );
center.x = x / 2 + point1.x;
center.y = y / 2 + point1.y;
rotate = atan2( y, x );
// 初期化(※『touchMultiFlag』で判断しているので注意)
if( !touchMultiFlag )
{
lengthBase = length;
centerBase = center;
rotateBase = rotate;
touchSingleFlag = FALSE;
touchMultiLock =
touchMultiFlag = TRUE;
}
touchMultiLength = length - lengthBase;
touchMultiCenter = center;
touchMultiRotate = rotate - rotateBase;
touchMultiMove.x = center.x - centerBase.x;
touchMultiMove.y = - center.y + centerBase.y;
}
//**************************************
// touchesParameterGet
//**************************************
- ( void ) touchesParameterGet:( NSSet* )touches event:( UIEvent* )event
{
static float scaleBackup, rotateBackup;
static CGPoint positionBackup;
static CGPoint pointBackup;
UITouch *touch = [touches anyObject];
// キャンセル時の処理
if( touch.phase == UITouchPhaseCancelled )
{
touchFlag =
touchSingleFlag =
touchMultiLock =
touchMultiFlag = FALSE;
return;
}
// マルチタッチ起動のチェック
// ※『[touches count]>1』は、『UITouchPhaseBegan』だけでなく『UITouchPhaseMoved』中にも来ます。
// ※そのためフラグとの組み合わせて起動をチェックしています。
if( !touchMultiFlag && ( [[event touchesForView:self] count] > 1 ) )
{
[self touchesMultiParameterGet:event];
scaleBackup = scale;
rotateBackup = rotate;
positionBackup = position;
}
// マルチタッチ解除
if( touchMultiLock && ( touch.phase == UITouchPhaseEnded ) && ( [touches count] == [[event touchesForView:self] count] ) )
{
touchFlag =
touchSingleFlag =
touchMultiLock =
touchMultiFlag = FALSE;
return;
}
// マルチタッチ処理
if( touchMultiFlag )
{
if( [touches count] <= 1 )
{
touchMultiFlag = FALSE;
return;
}
[self touchesMultiParameterGet:event];
scale = scaleBackup + touchMultiLength / SCALE_RATE;
rotate = rotateBackup - touchMultiRotate * 180 / PI;
position.x = positionBackup.x + touchMultiMove.x / MOVE_RATE;
position.y = positionBackup.y + touchMultiMove.y / MOVE_RATE;
return;
}
if( touchMultiLock )
return;
// シングルタッチ処理
touchSinglePoint = [touch locationInView:self];
switch( touch.phase )
{
case UITouchPhaseBegan:
touchFlag =
touchSingleFlag = TRUE;
pointBackup = touchSinglePoint;
positionBackup = position;
break;
case UITouchPhaseEnded:
touchFlag =
touchSingleFlag = FALSE;
break;
default:
if( !touchFlag )
return;
break;
}
touchSingleMove.x = touchSinglePoint.x - pointBackup.x;
touchSingleMove.y = -touchSinglePoint.y + pointBackup.y;
position.x = positionBackup.x + touchSingleMove.x / MOVE_RATE;
position.y = positionBackup.y + touchSingleMove.y / MOVE_RATE;
}
//**************************************
// touchesBegan
//**************************************
- ( void ) touchesBegan:( NSSet* )touches withEvent:( UIEvent* )event
{
[self touchesParameterGet:touches event:event];
}
//**************************************
// touchesMoved
//**************************************
- ( void ) touchesMoved:( NSSet* )touches withEvent:( UIEvent* )event
{
[self touchesParameterGet:touches event:event];
}
//**************************************
// touchesEnded
//**************************************
- ( void ) touchesEnded:( NSSet* )touches withEvent:( UIEvent* )event
{
[self touchesParameterGet:touches event:event];
}
//**************************************
// touchesCancelled
// ※電話の着信などの強制割り込み時に呼ばれます。
//**************************************
- ( void ) touchesCancelled:( NSSet* )touches withEvent:( UIEvent* )event;
{
[self touchesParameterGet:touches event:event];
}
//******************************************************************************
// End
//******************************************************************************
よもや、クソみそに言った「[[event touchesForView:self] count]」…。
これがキーワードだったとは…。
「touch-new.lzh」をダウンロード
最近のコメント