5

私はiPhoneアプリを構築しています。UIImageView サブクラス オブジェクトのセットを含む UIView があります。ユーザーはタッチで画像ビューをドラッグおよび回転できます。画像ビューを回転した後、画像ビューを移動するのに問題があります。

画像ビューを回転するには、変換回転を適用しますが、これは正常に機能します。次のようになります。

CGAffineTransform trans = self.transform;
self.transform = CGAffineTransformRotate(trans, delta);

ユーザーがタッチで要素を移動しようとすると、後で問題が発生します。touchesBegan:WithEvent: では、開始点をクラス変数 startLocation: に保存します。

- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{   
    // Retrieve the touch point
    CGPoint pt = [[touches anyObject] locationInView:self];
    startLocation = pt;
}

touchesMoved:withEvent: には、次のコードがありました。これは、画像ビューに回転変換がない場合でも十分に機能します。

- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
    CGPoint pt = [[touches anyObject] locationInView:self];
    CGFloat dx = pt.x - startLocation.x;
    CGFloat dy = pt.y - startLocation.y;
    CGPoint newCenter = CGPointMake(self.center.x + dx, self.center.y + dy);
    self.center = newCenter;
}

しかし、画像ビューに回転変換がある場合、画像ビューは touchesMoved イベントごとに画面上でスラッシングし、すぐに消えます。デバッガーで、pt の値が非常に大きくなっていることがわかりました。その点を変換する必要があることに気づき、次のようにしました。

- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
CGPoint pt = [[touches anyObject] locationInView:self];
if (!CGAffineTransformIsIdentity(self.transform)) {
    pt = CGPointApplyAffineTransform(pt, self.transform);
}

CGFloat dx = pt.x - startLocation.x;
CGFloat dy = pt.y - startLocation.y;
CGPoint newCenter = CGPointMake(self.center.x + dx, self.center.y + dy);
}

これははるかにうまく機能しました。画面上で画像をドラッグできるようになりました。ただし、変換の回転角度とイメージ ビューのサイズに応じて、最初の動きでイメージがいずれかの方向に 1 回揺れます。

最初の衝撃を与えずに画像ビューを移動するにはどうすればよいですか?

startLocation (タッチが開始されたときにキャプチャしたポイント) を変換する必要がないのはなぜですか?

4

2 に答える 2

1
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)_event {
    CGPoint pt = [[touches anyObject] locationInView:self]; 
    startLocation = pt;
} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)_event {
    CGPoint pt = [[touches anyObject] previousLocationInView:self];
    CGFloat dx = pt.x - startLocation.x;
    CGFloat dy = pt.y - startLocation.y;
    CGPoint newCenter = CGPointMake(self.center.x + dx, self.center.y + dy);
    self.center = newCenter;
}

- (void)setRotation:(float)rotation {
    self.transform = CGAffineTransformRotate(self.transform, degreesToRadians(rotation));
}
于 2011-03-07T05:32:06.280 に答える
0

座標をメインの非回転オブジェクトから回転ビュー システムに変換する必要があるようです。

UIView メソッド"convertPoint:toView:"を見てみましょう:

convertPoint:toView:

ポイントをレシーバーの座標系から指定されたビューの座標系に変換します。

- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view

パラメーター

レシーバーのローカル座標系 (境界) で指定されたポイント。

見る

座標系のポイントが変換されるビュー。view が nil の場合、このメソッドは代わりにウィンドウのベース座標に変換します。それ以外の場合、ビューとレシーバーの両方が同じ UIWindow オブジェクトに属している必要があります。

戻り値

ビューの座標系に変換されたポイント。

アップデート:

コメントへの応答:

指のタッチの「実際の」座標を(非回転システムで)取得する必要があります。次に、指が移動すると、常にメインの非回転ビューに新しい座標が表示されます。それらは変換する必要があるポイントです移動しているビューの回転したビューの親で。

  • Aが mainView 320x480ピクセルの場合
  • Bは、Aを中心とした 320x480ピクセルのサブビューです。
  • Cは、位置170,240 (画面中央の+10,+0 ) にあるBのサブビューです。
  • Bを時計回りに90度回転させます。
  • CB170,240のままです

しかし、画面では160,250で表示されます。

ユーザーが右に+20移動したい場合、ユーザーは指をBビュー座標ではなく画面座標で+20移動するため、ユーザーは画面の180,250で表示したいと考えています。この点B座標系に変換する必要があります...

少し簡単です。ユーザーが指を動かしたときに指の画面座標を取得し、それを回転ビュー座標 ( B ) に変換するだけです...

于 2011-02-01T07:11:27.900 に答える