4

iPhone の CALayer 描画で奇妙な問題が発生しています。「泡」を表す一連のサブレイヤーを追加するルートレイヤーがあります。最終結果は次のようになります。

http://www.expensivedna.com/IMG_0018.PNG http://www.expensivedna.com/IMG_0018.PNG

問題は、レイヤーをアンチエイリアスにできないように見えることです (バブルのギザギザに注意してください)。バブル CALayer の drawInContext を上書きする私のコードは次のとおりです。

- (void)drawInContext:(CGContextRef)theContext{
CGContextSetAllowsAntialiasing(theContext, true);
CGContextSetShouldAntialias(theContext, true);

size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 1.0, 1.0, 1.0, 0.5,  // Start color
                          1.0, 1.0, 1.0, 0.0 }; // End color
CGColorSpaceRef rgbColorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef glossGradient = 
CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);

CGPoint topCenter = CGPointMake(25, 20);
CGPoint midCenter = CGPointMake(25, 25);
CGContextDrawRadialGradient(theContext, glossGradient, midCenter, 20, topCenter, 10, kCGGradientDrawsAfterEndLocation); 

}

ここで非常に奇妙なのは、描画コードをわずかに変更して、次のように通常の赤い円のみを描画することです。

- (void)drawInContext:(CGContextRef)theContext{
CGContextSetAllowsAntialiasing(theContext, true);
CGContextSetShouldAntialias(theContext, true);

CGContextSetFillColorWithColor(theContext, [UIColor redColor].CGColor);
CGContextFillEllipseInRect(theContext, CGRectMake(0, 0, 40,40));
}

すべてがアンチエイリアスに問題ないようです:

http://www.expensivedna.com/IMG_0017.PNG http://www.expensivedna.com/IMG_0017.PNG

この一見奇妙な動作を理解できないようです。アンチエイリアシング グラデーションと通常の円の違いがわかりませんか?

みんなありがとう。

4

3 に答える 3

4

みんなありがとう。したがって、答えは2つの答え(coobとAlex)の組み合わせであることがわかります。基本的に、CGDrawRadialGradient関数には、終了円ではなく、開始円にのみエイリアシングがあるようです。両方にエイリアスの「エッジ」が必要なので、最初に、最初の「エッジ」を処理する関数を裏返しに描画するように設定しますが、次のようになります。

ステップ1

次に、coobによって提案されたように画像をクリップします。これにより、バブルの最後のエッジの周りに優れたエイリアシングが得られます。

ステップ2

私には十分に見えます!

- (void)drawInContext:(CGContextRef)theContext{
CGContextSetAllowsAntialiasing(theContext, true);
CGContextSetShouldAntialias(theContext, true);

size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 1.0, 1.0, 1.0, 0.0,  // Start color
              1.0, 1.0, 1.0, 0.5 }; // End color
CGColorSpaceRef rgbColorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef glossGradient = 
CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);

CGContextAddEllipseInRect(theContext, CGRectMake(5, 5, 40, 40));
CGContextClip(theContext);

CGPoint topCenter = CGPointMake(25, 20);
CGPoint midCenter = CGPointMake(25, 25);
CGContextDrawRadialGradient(theContext, glossGradient, topCenter, 10, midCenter, 20, kCGGradientDrawsAfterEndLocation);

}

于 2009-05-09T22:27:52.383 に答える
2

Jeff - topCenter をもう少し外側に配置し、円形マスクで CGContextClipToMask を使用します。

編集: 実際には、CGContextClip を使用してベクター クリッピング パスを使用する方がはるかに優れた方法です。

編集 2: サンプル コード:

CGContextAddEllipseInRect(theContext, CGRectMake(20, 20, 10, 10));
CGContextClip(theContext);

グラデーションを描画する前にこれを追加し、少し外側に描画します。

于 2009-05-08T13:18:34.510 に答える
0

kCGGradientDrawsAfterEndLocation を削除してみてはいかがでしょうか。アルファで何か変なことをしているかもしれません

于 2009-04-22T15:13:29.007 に答える