4

図面ビューを美しくズームするための解決策を探しています。私のアプリでは、別の UIView (描画ビューのように使用されます) を持つビューがあり、それにストロークを描くと、ストロークは完璧です。しかし、ビューをズームすると、この非常に醜い効果 (ピクセル化されたストローク) が得られます: (ソース: imagup.com )スクリーンショット

URL 画像

適切なストロークを持つための解決策はありますか?

私の UIViewController には次のような階層があります。

  • UIViewController
    • ScrollView
      • ビューのズーム可能 (viewForZoomingInScrollView メソッドで定義)
        • 画像表示
        • 図面ビュー

どうもありがとう !

よろしく、セバスチャン;)

4

3 に答える 3

4

私はベクトル描画アプリケーションを作成中ですが、これを正しく行うのは簡単な作業ではなく、かなりの作業が必要です。

留意すべきいくつかの問題:

  • ベクター グラフィックスを使用していない場合 (たとえば、CGPath はベクターです)、ピクセレーションを削除することはできません。たとえば、UIImage の解像度はそれほど大きくありません。
  • 描画がピクセル化されないようにするには、すべてを再描画する必要があります。大量の描画がある場合、これは実行するのにコストのかかる作業になる可能性があります。
  • 過度に大きなコンテキストが必要になり、描画がデバイスの能力を超える可能性があるため、ズーム中に良好な解像度を持つことはほとんど不可能です

私はコア グラフィックスを使用して描画を行っているため、複数の CGContext を割り当てて管理し、それらをバッファーとして使用することで、この問題を解決しました。常に最小ズーム レベル (倍率 1) で保持されているコンテキストが 1 つあります。そのコンテキストは常に引き込まれ、ズームを完全に解除するときに、再描画が既に行われているため、再描画に時間を費やさないようにします。別のコンテキストは、ズーム時に描画するためだけに使用されます。ズームされていない場合、そのコンテキストは無視されます (新しいズーム レベルに基づいて再描画する必要があるため)。ズームを実行する方法の高レベルのアルゴリズムは次のとおりです。

- (IBAction)handlePinchGesture:(UIGestureRecognizer *)sender
{
    if(sender.state == UIGestureRecognizerStateBegan)
    {
         //draw an image from the unzoomedContext into my current view

             //set the scale transformation of my current view to be equal to "currentZoom", a property of the view that keeps track of the actual zoom level
    }
    else if(sender.state == UIGestureRecognizerStateChanged)
    {
         //determine the new zoom level and transform the current view, keeping track in the currentZoom property

             //zooming will be pixelated.
    }
    else if(sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateCancelled)
    {
             if(currentZoom == 1.0)
             {
                   //you are done because the unzoomedContext image is already drawn into the view!
             }
             else
             {
                   //you are zoomed in and will have to do special drawing

                   //perform drawing into your zoomedContext
                   //scale the zoomedContext

                   //set the scale of your current view to be equal to 1.0

                   //draw the zoomedContext into the current view.  It will not be pixelated!

                   //any drawing done while zoomed needs to be "scaled" based on your current zoom and translation amounts and drawn into both contexts
             }

    }

}

たくさんの描画がある場合、パスのイメージを描画する方がパスを描画するよりもはるかに高速であるため、バッファー用の追加のバッファーがあるため、これはさらに複雑になります。

複数のコンテキストを管理し、コードを調整して複数のコンテキストに効率的に描画し、適切な OOD に従い、現在のズームと変換に基づいて新しい描画をスケーリングするなど、これは山のようなタスクです。うまくいけば、これがあなたのやる気を起こさせ、あなたを正しい軌道に乗せるか、そのピクセル化を取り除くことは努力する価値がないと判断するでしょう:)

于 2012-08-28T14:59:10.457 に答える
1

私は同じ問題を抱えていて、解決策を見つけました。ビューにCATiledLayerバッキングレイヤーとして使用するように指示し、ビューがサポートするズームのレベルをビューに伝えます。(親)ビューがズームされると、描画メソッドが自動的に呼び出されます。

levelsOfDetailとの簡単な説明levelsOfDetailBias:

  • levelsOfDetailズーム レベルの合計数を決定する
  • levelsOfDetailBiasズームインしている数を特定します。

したがって、私の例では 4 つのズーム レベルがあり、3 つはズーム インされ、1 つは非ズーム レベルです。つまり、ビューはズーム イン時にのみ再描画されます。

@imprementation MyZoomableView

+ (Class)layerClass
{
    return [CATiledLayer class];
}


- (id)initWithFrame:(CGRect)frame
{
    if ((self = [super initWithFrame:frame])) {
        ((CATiledLayer *)self.layer).levelsOfDetail = 4;
        ((CATiledLayer *)self.layer).levelsOfDetailBias = 3;
    }
    return self;
}

@end
于 2012-10-02T06:33:48.913 に答える
0

デリゲート メソッドで使用[self setContentScaleFactor:scale];します。scrollViewDidEndZooming:

于 2013-05-14T10:30:48.417 に答える