工場裏のアーカイブス

素人によるiPhoneアプリ開発の学習記

ピンチ操作による拡大縮小

例えば写真や3Dモデルなどのビューワーアプリ、あるいは地図アプリなどでは、ピンチ操作(2本の指を画面に振れさせ、摘むように指同士を近づけたり、あるいは遠ざけたりする操作)によって対象を拡大縮小する機能がよく備えられています。そこで、前の記事で作成した(クォータニオンを用いて)ドラッグ操作でモデルを回転させることが出来るアプリに、更にピンチ操作によりモデルの拡大縮小を行う機能を追加してみます。

Pinch Gesture Recognizer の利用

ピンチ操作を検出するための方法はいくつかあるようですが、XCode(この記事執筆時点のバージョンは4.6)のStoryboardのObject Libraryには、「Pinch Gesture Recognizer」というそのものズバリなオブジェクトが用意されていますので、これを用いる方法についてメモします(以下のメモは、前の記事で作成したアプリに付け足していく形とします。また、この方法はあくまで自己流であり、他にも方法があるかもしれません)。

  • 最初に ViewController.h に、以下のようにデリゲート(UIGestureRecognizerDelegate)を追加します。
//ViewController.h
#import <UIKit/UIKit.h>
#import <GLKit/GLKit.h>

@interface ViewController : GLKViewController<UIGestureRecognizerDelegate>

@end


  • 続いて、Storyboard 上で Object Library から Pinch Gesture Recognizer を探し、View の上にドラッグ&ドロップします。

f:id:fleron:20130503170828p:plain

  • Pinch Gesture Recognizer のアイコンが追加されますので、このアイコンから ViewController のアイコンまで Control キーを押しながら(あるいは、右クリックをしながら)ドラッグ&ドロップします。ドラッグ時に青線が表示されるはずです。ドロップすると下図のようなポップアップが表示されますので、「Outlets」の下にある「delegate」を左クリックします。これで ViewController がピンチ操作を検知するようになります。

f:id:fleron:20130503171740p:plain

  • あとは、ピンチ操作検出時のアクションを設定します。まず下図のように ViewController.h を表示し、Pinch Gesture Recognizer のアイコンから ViewController.h の適当な行まで、Control キーを押しながら(あるいは右クリックをしながら)ドラッグ&ドロップします。

f:id:fleron:20130503173700p:plain

  • すると下図のようなダイアログが表示されますので、「Connection」の種類を「Action」にし、適当な名前(ここでは pinchGestureRecognized としました)を付けて、「Connect」ボタンをクリックします。

f:id:fleron:20130503211801p:plain

  • これで、ViewController.m の中に、以下のようにピンチ操作を検知するたびに呼び出されるアクションメソッドが自動的に追加されます。
//ViewController.m の末尾に自動的に追加
- (IBAction)pinchGestureRecongized:(id)sender {
}


  • あとはアクションメソッドの中に、以下のようにモデルの拡大縮小を行うための処理を記述します。
- (IBAction)pinchGestureRecongized:(id)sender {
    GLfloat factor = [(UIPinchGestureRecognizer *)sender scale];
    
    eyeDist += eyeDist * (1.0f - factor) * 0.05f;
    if(eyeDist > -5.0f) eyeDist = -5.0f;
    if(eyeDist < -100.0f) eyeDist = -100.0f;
}

ここでは単純に、視点からモデル中心までの距離を表す変数(eyeDist 変数)の値を操作する方法をとります。以下のように scale プロパティを介して、ピンチ操作の倍率(最初に指を置いた位置に対して、指同士がどれだけ近づいたか(または離れたか))を取得することが出来ます。

 GLfloat factor = [(UIPinchGestureRecognizer *)sender scale];

そして倍率(eyeDist は負の値ですので、(1.0f - factor) という計算を噛ませてあります)、および現在の eyeDist の値に比例させた補正値をeyeDist に加算します。補正値を現在の eyeDist の値に比例させるのがポイントであり、これによって常に一定の速度で拡大縮小が行われるように見せることが出来ます(これについては、もっとスマートな方法があるかもしれませんが…)。

実行してピンチ操作をしてみてください(iPhone シミュレータ上であれば、option キーを押しながらシミュレータの画面上をドラッグするとピンチ操作が入力出来ます。2つの白い円が、2本の指先の位置を表します)。ピンチインによってモデルが縮小され、ピンチアウトによってモデルが拡大されます。
f:id:fleron:20130503220347p:plain