1

限られた地域のカスタム マップがあり、ユーザーの位置を正しく表示するように設定しています。マップは、UIScrollView 内の 1600 ピクセルの正方形の画像です。

ユーザーの現在の位置を示す十字線の画像があります。これは、zoomScale 1.0 で目的のサイズです。scrollView をつまんでズームすると、十字線がそれに合わせて拡大縮小されます。サブビューを画面上で同じサイズのままにしたいと思います。

これに関する情報を見つけることができませんでした。これについて最善の方法は何でしょうか?

答えを助けるために私があなたに提供できるものがあれば、私に知らせてください.

どうもありがとう!

編集 -

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scaleこれをさらに調べたところ、マーカーの現在の中心とサイズを取得して調整するために使用しようとした UIScrollViewDelegate メソッドがありますが、これはズームの最後でのみスケーリングされます。ユーザーがズームしている間、マーカーを同じサイズのままにしたいと思います。

編集2-

Cake は以下に素晴らしい回答を提供してくれましたが、私が想像していた方法でこれを実装することはできませんでした。

アルファを 0 に設定して、UIImageView をプレースホルダーとして使用しています。このプレースホルダーは、マップに対して相対的に移動し、ユーザーの位置を示します。これは期待どおりに動作します。残念ながら、これはマップのサブビューであるため、マップに合わせてサイズが変更されます (そのため、所定の位置に留まります)。

以下のCakeの回答を参考にして、非スケーリングの十字線画像を作成し、それを兄弟サブビューとしてスクロールビューに追加しました。Cake がそれらを指摘した後、十字線の新しいフレームを取得するための数学は非常に簡単でした。

    CGPoint ULPC = userLocationPlaceholder.center;
    float zs = scrollView.zoomScale;
    CGRect newFrame = CGRectMake(((ULPC.x * zs) - scrollView.contentOffset.x) - 20, ((ULPC.y * zs) - scrollView.contentOffset.y) - 20, 40, 40);

画像の幅が 40 ポイントの場合。これはセンターに完全に一致します。

私が今抱えている問題は、十字線の画像をプレースホルダーにロックしたままにできないことです。

私は自己呼び出しアニメーションを次のように使用してみました:

-(void)animeUserLocationAttachment
{
[UIView animateWithDuration:0.05 
                      delay:0 
                    options:(UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionCurveLinear )
                 animations:^{
                     userLocationDotContainer.frame = newFrame;
               } completion:^(BOOL finished){
                     // Call self
                     [self animateUserLocationAttachment];
                 }];
}

スクロール/ズームを開始するとすぐに、これによりアニメーションがロックされ、スクロール/ズームを解除するまで十字線が所定の位置に留まり、位置が正しく更新されます。

これを回避する方法、または適用できる代替方法はありますか?

どうもありがとう

編集3 -

問題の90%をカバーしているため、Cakeの回答を再承認しました。彼の答えに加えて、ScrollViewDelegate メソッドを実装scrollViewWillBeginDragging:scrollViewWillBeginDecelerating:、マップに対する十字線の現在のサイズに合わせてプレースホルダーをスケーリングし、プレースホルダー (マップ イメージのサブビュー) を表示し、十字線イメージを非表示にします。デリゲート メソッドscrollviewWillBeginZooming:withView:は、マップに合わせてスケーリングされるため、プレースホルダーを表示しません。Cake が推奨するように、この問題について新しい質問を作成します。

対応するメソッド ( scrollViewDidEndZooming:withView:atScale:scrollViewDidEndDragging:willDecelerate:および -scrollViewDidEndDecelerating:`) はすべてプレースホルダーを非表示にし、十字線を再表示します。

4

3 に答える 3

2

スクロールビューを含むビューまたはビュー コントローラーに関連付けられた別の十字線イメージを作成します。次に、これを常に既存の十字線画像の中心にスナップさせます。次に、元の十字線の画像を非表示にします。次に、スクロールビューが関連付けを解除された十字線をスケーリングすることを回避でき、同じサイズのままにする必要があります。

相対座標系

ココア タッチの各ビューには、原点を持つフレーム プロパティがあります。あるビューが所有するオブジェクトを別のビューに対して適切に配置するために必要なことは、それらの起源の違いを理解することだけです。あるビューが別のビューのサブビューである場合、これはそれほど難しくありません。

  • コンテナー ビューのオリジンを取得する
  • コンテナ ビュー内のサブビューの位置を取得する
  • サブビューの原点を取得する
  • 原点位置の差を計算する
  • オーバーラップするオブジェクトの位置を取得します (サブビューに対して)
  • コンテナ ビューを基準にしてオーバーラップするオブジェクトの位置を計算します
  • 十字線をこの位置に移動します
于 2012-06-22T19:25:13.183 に答える
1

ミックの答えに相当するスウィフト:

class MapContainerView:UIView {
    @IBOutlet var nonScalingViews: [UIView]!

    override var transform: CGAffineTransform {
        didSet {
            guard let nonScalingViews = nonScalingViews else {
                return
            }
            let invertedTransform = CGAffineTransformInvert(transform)
            for view in nonScalingViews {
                view.transform = invertedTransform
            }
        }
    }
}
于 2016-06-16T11:25:53.393 に答える