ピンチジェスチャの方向

簡単な紹介



プロジェクトの1つで、ピンチジェスチャの方向を決定する必要がありました。 これは、軸に沿ってオブジェクトを選択的にスケーリングするために必要でした。 つまり 指が垂直方向に動く/伸びる場合、オブジェクトを垂直方向にのみ拡大縮小します。 残念ながら、UIPinchGestureRecognizerの標準ジェスチャレコグナイザーはこの情報を提供しません。 Google検索結果の最初のページを見て、既製のソリューションにつまずきませんでした。 「まあ、自分で書いてください。 さらにおもしろい:)」-私はピンチを考えて実装し始めました。





編集中



2010年7月10日-ソースコードが更新されました。 oScaleプロパティ(CGPoint)を追加しました。 個々の軸のスケーリング係数が含まれています。 UIPinchGestureRecognizerによるスケールのアナログ。



主な開発



ピンチの実行時に指の向きを決定するには、2つのサブタスクを解決する必要があります。

  1. ピンチジェスチャ自体を識別する
  2. 指の角度を決定する


最初のサブタスクに問題はありませんでした。 もう一度ドキュメントを読んだ後、UIGestureRecognizer、つまりUIPinchGestureRecognizerに基づいてジェスチャーの「認識機能」を作成できるようになるずっと前からすべてが完了していることを確認しました。

2番目のサブタスクの解決にも時間がかかりませんでした。 少し考えた後

画像

私は解決策を見つけました:画面のOy軸とユーザーの指を通る線の間の角度を単純に決定します。



コードを書くためにあらゆることが行われます。 作業の結果は次のとおりです。



説明:



// // UIOrientedPinchGestureRecognizer.h //  .. // #import <Foundation/Foundation.h> #import "UIKit/UIGestureRecognizerSubclass.h" typedef enum{ OrientationNone = 0, OrientationVertical = 1, OrientationHorizontal = 2, OrientationDiagonal = 3, OrientationInvertedDiagonal = 4 }Orientation; @interface UIOrientedPinchGestureRecognizer : UIPinchGestureRecognizer { Orientation _orientation; CGFloat _angle; CGPoint _lastScale; CGFloat _oldScale; } //  @property (nonatomic) Orientation orientation; // ,  OY.  .  0  PI.  angle==PI_2 orientation==OrientationHorizontal @property (nonatomic) CGFloat angle; @property (nonatomic) CGPoint oScale; @end #pragma mark c_func static inline CGFloat degToRad(CGFloat deg) {return deg*M_PI/180;} static inline CGFloat radToDeg(CGFloat rad) {return rad*180/M_PI;} //     .     A, .   PointB-PointA-PointC static inline double getCosAngle(CGPoint pointA,CGPoint pointB, CGPoint pointC){ CGPoint vectorAB = CGPointMake(pointB.x-pointA.x, pointB.y-pointA.y); CGPoint vectorAC = CGPointMake(pointC.x-pointA.x, pointC.y-pointA.y); double dAB=sqrt(vectorAB.x*vectorAB.x+vectorAB.y*vectorAB.y); double dAC=sqrt(vectorAC.x*vectorAC.x+vectorAC.y*vectorAC.y); double scal = vectorAB.x * vectorAC.x +vectorAB.y * vectorAC.y; double angle = scal/(dAB*dAC); return angle; } //    .     A, .   PointB-PointA-PointC static inline double getAngle(CGPoint pointA,CGPoint pointB, CGPoint pointC){ if ((CGPointEqualToPoint(pointA, pointB))||(CGPointEqualToPoint(pointA, pointC))||(CGPointEqualToPoint(pointB, pointC))) return 0; //     3,  2     return acos(getCosAngle(pointA, pointB, pointC)); } #pragma -
      
      







実装:



 // // UIOrientedPinchGestureRecognizer.m // #import "UIOrientedPinchGestureRecognizer.h" @implementation UIOrientedPinchGestureRecognizer @synthesize angle=_angle, orientation=_orientation,oScale=_lastScale; #pragma mark init/dealloc -(void) dealloc{ [super dealloc]; } -(id) init{ self = [super init]; if (self) { _orientation = OrientationNone; _angle = 0; } return self; } #pragma mark - Methods -(void) detectAngle:(NSArray *) touches{ if ([touches count]!=2) { _orientation= OrientationNone; _angle = 0; //     //  .   _lastScale.x *= self.scale/_oldScale; _lastScale.y *= self.scale/_oldScale; _oldScale = self.scale; return; } //   CGPoint firstPoint =[[touches objectAtIndex:0] locationInView:self.view]; CGPoint secondPoint = [[touches objectAtIndex:1] locationInView:self.view]; //   OY if (secondPoint.x<firstPoint.x) { CGPoint tmp = secondPoint; secondPoint = firstPoint; firstPoint = tmp; } //  _angle = getAngle(firstPoint,secondPoint,CGPointMake(firstPoint.x,firstPoint.y-100.0f)); //    if ((_angle> M_PI_4/2.0f)&&(_angle< M_PI_4+M_PI_4/2.0f)) { _orientation= OrientationDiagonal; _lastScale.x *= self.scale/_oldScale; _lastScale.y *= self.scale/_oldScale; }else if ((_angle> M_PI_4+M_PI_4/2.0f)&&(_angle<M_PI_2+M_PI_4/2.0f)) { _orientation = OrientationHorizontal; _lastScale.x *= self.scale/_oldScale; }else if ((_angle>M_PI_2+M_PI_4/2.0f)&&(_angle<M_PI_2+M_PI_4+M_PI_4/2.0f)){ _orientation = OrientationInvertedDiagonal; _lastScale.x *= self.scale/_oldScale; _lastScale.y *= self.scale/_oldScale; }else{ _orientation=OrientationVertical; _lastScale.y *= self.scale/_oldScale; } _oldScale=self.scale; return; } -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ _lastScale = CGPointMake(1.0f, 1.0f); _oldScale = 1.0f; [self detectAngle:[touches allObjects]]; [super touchesBegan:touches withEvent:event]; } -(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ [self detectAngle:[touches allObjects]]; [super touchesMoved:touches withEvent:event]; } @end
      
      







UIPinchGestureRecognizerとして使用



 UIOrientedPinchGestureRecognizer *pinchGesture = [[UIOrientedPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGesture:)]; [pinchGesture setDelegate:self]; pinchGesture.cancelsTouchesInView=NO; [self.view addGestureRecognizer:pinchGesture];
      
      







処理中:



 - (IBAction)handlePinchGesture:(UIOrientedPinchGestureRecognizer *)sender { NSLog(@"angle: %f orientation: %i scale.x:%f scale.y:%f",radToDeg(sender.angle),sender.orientation,sender.oScale.x,sender.oScale.y); }
      
      







短所:



現在、3/4などの角度の定義はありません。 指。



ソース





ご清聴ありがとうございました。



All Articles