4

そのため、iOS 4.2 を使用してズームとパンをアプリケーションに追加しています。UIPinchGestureRecognizer と UIPanGestureRecognizer のインスタンスを実装しました。一度にジェスチャーを認識しているのは、これらのうちの1つだけのようです。特に、後者は 1 本の指が押されたときにのみ反応しますが、前者は 2 番目の指が存在するときに反応します。それは問題ありませんが、ユーザーエクスペリエンスの質を低下させると思われる副作用がいくつかあります.

2 本の指を下に置き、そのうちの 1 本を動かすと、画像は本来のように拡大 (ズームイン) しますが、指の下のピクセルは指の下にありません。画像は、2 本の指の中間点ではなく、画像の中心からスケーリングされます。そして、その中心点自体が動いています。その中心点の動きが画像全体のパンを決定するようにしたい.

ほぼすべての iOS アプリケーションで、指を追跡する指の下のピクセルではなく、画像の中心付近で画像がズームインまたはズームアウトするという同じ動作がありますか?

カスタム ジェスチャ認識エンジンを作成することは、この問題に対する正しい設計アプローチのように思えますが、商業的に無料でダウンロードして使用するために、誰かがそのような認識エンジンを作成したようにも思えます。そのようなUIGestureRecognizerはありますか?

4

3 に答える 3

4

そのため、望ましい結果を達成するためのより良いソリューションを誰も提供してくれなかったことを考慮して、カスタム ジェスチャ認識エンジンを作成しました。以下は、指の下のピクセルが指の下にまったく残るように、カスタム認識エンジンがビューを再配置する場所と、重心をパンおよびズーム効果の中心として使用する新しいスケールを示すことを可能にする主要なコード フラグメントです。指が回転しているように見える場合を除きますが、これはサポートされておらず、そのようなジェスチャーを止めることはできません。このジェスチャ認識機能は、2 本の指で同時にパンとズームを行います。2 本の指のうちの 1 本が持ち上げられた場合でも、後で 1 本の指でパンするためのサポートを追加する必要があります。

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    // We can only process if we have two fingers down...
    if ( FirstFinger == nil || SecondFinger == nil )
        return;

    // We do not attempt to determine if the first finger, second finger, or
    // both fingers are the reason for this method call. For this reason, we
    // do not know if either is stale or updated, and thus we cannot rely
    // upon the UITouch's previousLocationInView method. Therefore, we need to
    // cache the latest UITouch's locationInView information each pass.

    // Break down the previous finger coordinates...
    float A0x = PreviousFirstFinger.x;
    float A0y = PreviousFirstFinger.y;
    float A1x = PreviousSecondFinger.x;
    float A1y = PreviousSecondFinger.y;
    // Update our cache with the current fingers for next pass through here...
    PreviousFirstFinger = [FirstFinger locationInView:nil];
    PreviousSecondFinger = [SecondFinger locationInView:nil];
    // Break down the current finger coordinates...
    float B0x = PreviousFirstFinger.x;
    float B0y = PreviousFirstFinger.y;
    float B1x = PreviousSecondFinger.x;
    float B1y = PreviousSecondFinger.y;


    // Calculate the zoom resulting from the two fingers moving toward or away from each other...
    float OldScale = Scale;
    Scale *= sqrt((B0x-B1x)*(B0x-B1x) + (B0y-B1y)*(B0y-B1y))/sqrt((A0x-A1x)*(A0x-A1x) + (A0y-A1y)*(A0y-A1y));

    // Calculate the old and new centroids so that we can compare the centroid's movement...
    CGPoint OldCentroid = { (A0x + A1x)/2, (A0y + A1y)/2 };
    CGPoint NewCentroid = { (B0x + B1x)/2, (B0y + B1y)/2 };    

    // Calculate the pan values to apply to the view so that the combination of zoom and pan
    // appear to apply to the centroid rather than the center of the view...
    Center.x = NewCentroid.x + (Scale/OldScale)*(self.view.center.x - OldCentroid.x);
    Center.y = NewCentroid.y + (Scale/OldScale)*(self.view.center.y - OldCentroid.y);
}

ビュー コントローラーは、問題のビューに新しいスケールと中心を割り当てることによって、イベントを処理します。他のジェスチャ レコグナイザーでは、コントローラーが一部の計算を実行できる傾向があることに気付きましたが、すべての計算をレコグナイザーで実行しようとしました。

-(void)handlePixelTrack:(PixelTrackGestureRecognizer*)sender
{
    sender.view.center= sender.Center;
    sender.view.transform = CGAffineTransformMakeScale(sender.Scale, sender.Scale);
}
于 2012-08-10T04:41:03.137 に答える
1

より簡単な解決策は、ビューをスクロール ビュー内に配置することです。次に、ピンチ アンド パンを無料で利用できます。それ以外の場合は、パンとピンチの両方のジェスチャ デリゲートを自分自身に設定し、shouldRecognizeSimultaneously に対して YES を返すことができます。ユーザーの指の中心にズームインすることに関しては、私はそれを正しく解決したことはありませんがanchorPoint、スケールを変更する前にビューのレイヤーを操作する必要があります (私は思います)。

于 2012-08-07T23:51:25.787 に答える