2009-04-22 3 views
2

私のアプリケーションのビューの1つの背景として、私はかなり単純な長方形の枠をその枠の中に描画したいと思います。これは本質的に長方形の勾配です:フレームの周りの黒い線が白く10-20ピクセルほど白くなります。残念ながら、Core Graphicsは角勾配(CGGradientまたはCGShading)を提供しません。だから私は最高のアプローチが何になるのだろうかと思っています。私に発生Quartz 2D/Core Graphicsでこの図を完成させる最も良い方法は?

2:

  1. 同心四角形の一連を描き、各次の1色が薄く、かつそれぞれの側に1ピクセルによってインセット。私はより簡単なアプローチは考えられませんが、私はすべての勾配計算を自分で行う必要があり、多くのグラフィックス操作が必要になります。
  2. CGGradientを線形モードで各側に1回使用します。しかし、これがうまくいくためには、最初に両側に台形のクリッピング領域を設定して、グラデーションがコーナーではさまれるようにする必要があると思います。

これを行うためになでるパスを使用する方法である必要がありますが、それぞれの側に異なる向きだパターンを定義する方法がありますように、それは思われないように思えます。

+0

エッジ毎CGGradientを使用すると、より速くなりますが、それはまだあまりにも遅いです場合は、キャッシュとしてUIImageを使用することができます(一度UIImageに描き、その後、必要なときにビューに画像を描画) – rpetrich

+0

うん私はどのようなアプローチをとっていても、結果をイメージにキャッシュするのは良い考えであると思います。しかし、私はアプリでPNGを出荷するのではなく、手作業で図面をやるという考えのようなものです。 –

答えて

3

私はオプション#2となるだろう:一度各側に、リニアモードで

使用CGGradient。しかし、これがうまくいくためには、最初に両側に台形のクリッピング領域を設定して、グラデーションがコーナーではさまれるようにする必要があると思います。

台形領域を作成するためにNSBezierPathを使用するとかなり簡単で、4回の描画操作を実行するだけで済みます。

はここで左側の台形領域を形成するための基本的なコードです:このような

NSRect outer = [self bounds]; 
NSPoint outerPoint[4]; 
outerPoint[0] = NSMakePoint(0, 0); 
outerPoint[1] = NSMakePoint(0, outer.size.height); 
outerPoint[2] = NSMakePoint(outer.size.width, outer.size.height); 
outerPoint[3] = NSMakePoint(outer.size.width, 0); 

NSRect inner = NSInsetRect([self bounds], borderSize, borderSize); 
NSPoint innerPoint[4]; 
innerPoint[0] = inner.origin; 
innerPoint[1] = NSMakePoint(inner.origin.x, 
          inner.origin.y + inner.size.height); 
innerPoint[2] = NSMakePoint(inner.origin.x + inner.size.width, 
          inner.origin.y + inner.size.height); 
innerPoint[3] = NSMakePoint(inner.origin.x + inner.size.width, 
          inner.origin.y); 

NSBezierPath leftSidePath = [[NSBezierPath bezierPath] retain]; 
[leftSidePath moveToPoint:outerPoint[0]]; 
[leftSidePath lineToPoint:outerPoint[1]]; 
[leftSidePath lineToPoint:innerPoint[1]]; 
[leftSidePath lineToPoint:innerPoint[0]]; 
[leftSidePath lineToPoint:outerPoint[0]]; 

// ... etc. 

[leftSidePath release]; 
+0

iPhone(またはMac)でたくさんのグラフィックスプログラミングをまだ行っていない(明らかに?)人は、NSBezierPathを好む理由がありますか?私が見たほとんどの例は、Core Graphics APIに集中しています。 –

+0

これまで私が使用していたので、ここで使用しました。 :) Core Graphicsがそれをもっと良くすることができるのは完全に可能です。試しても害はありませんが、測定可能なパフォーマンスが向上しているかどうかを確認するためにコードをプロファイルしてください(実際に必要な場合)。 –

+0

これはまさに私が結んだコードではありませんが、そんなに似ていません。 4台の台形を描くよりも優れた解決策は考えられませんでした。 –

0

何かも仕事ができます。 基本的に、クリッピングパスを使用する代わりに、単純にブレンドモードを使用します。 この例では、グラデーションはCGLayerにキャッシュされています。

CGContextRef ctx = UIGraphicsGetCurrentContext(); 
CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB(); 

CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0); 
CGContextFillRect(ctx,self.bounds); 

CGFloat w = self.bounds.size.width; 
CGFloat h = self.bounds.size.height; 
CGFloat dh = (w-h)/2; 

CGLayerRef l = CGLayerCreateWithContext(ctx,CGSizeMake(h,48.0f),NULL); 
CGContextRef lctx = CGLayerGetContext(l); 

float comp[] = { .2,.5,1.0,1.0,1.0,1.0,1.0,1.0}; 
CGGradientRef gradient = CGGradientCreateWithColorComponents(cspace, comp, NULL, 2); 
CGContextDrawLinearGradient(lctx, gradient,CGPointMake(0,0),CGPointMake(0,48), 0); 

CGContextSaveGState(ctx); 
CGContextSetBlendMode(ctx,kCGBlendModeDarken); 
for(int n=1;n<5;n++) 
{ 
    CGContextTranslateCTM(ctx,w/2.0,h/2.0); 
    CGContextRotateCTM(ctx, M_PI_2); 
    CGContextTranslateCTM(ctx,-w/2.0,-h/2.0); 
    CGContextDrawLayerAtPoint(ctx,CGPointMake((n%2)*dh,(n%2)*-dh),l); 
} 
CGContextRestoreGState(ctx); 
関連する問題