使用Quartz 2D / Core Graphics完成此绘图的最佳方法是什么?

时间:2009-04-22 14:48:14

标签: iphone objective-c quartz-graphics

作为我的应用程序中某个视图的背景,我想在其框架内绘制一个相当简单的矩形边框。这基本上是一个矩形渐变:框架周围的黑色线条,淡入白色约10-20像素。不幸的是,据我所知,Core Graphics不提供矩形渐变(使用CGGradientCGShading)。所以我想知道最好的方法是什么。

我发生了两件事:

  1. 绘制一系列同心矩形,每个随后一个颜色较浅,每边插入1px。我想不出更简单的方法,但我必须自己完成所有的梯度计算,这可能是很多图形操作。
  2. 在线性模式下使用CGGradient,每侧一次。但为了实现这一点,我认为我需要首先为每一侧设置一个梯形剪裁区域,以便在角落处斜接渐变。
  3. 似乎应该是一种使用路径描边来实现此目的的方法,但似乎没有办法定义一个在每一方面都有不同方向的模式。

2 个答案:

答案 0 :(得分:3)

我会选择#2选项:

  

在线性模式下使用CGGradient,每侧一次。但为了实现这一点,我认为我需要先为每一侧设置一个梯形剪裁区域,以便在角落处对渐变进行斜接。

使用NSBezierPath创建梯形区域非常简单,您只需要执行四次绘图操作。

以下是创建左侧梯形区域的基本代码:

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];

答案 1 :(得分:0)

这样的事情也可以起作用。 基本上:不使用剪切路径,只需使用blendmode。 在此示例中,渐变缓存在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);