【问题标题】:CGContextDrawLinearGradient confusion. Need clarificationCGContextDrawLinearGradient 混乱。需要澄清
【发布时间】:2014-03-10 04:13:31
【问题描述】:

我一直在尝试使用 CGContextDrawLinearGradient,但我对起点和终点的含义感到非常困惑?我认为它们的意思是当前 CGContext 上的坐标,所以如果我将起点定义为 0,0 并将终点定义为 100,100,我会得到一个带有渐变的正方形。我得到了完全无法连接到我的坐标的其他东西。

这是我的代码:

- (void)drawRect:(CGRect)rect {
// Drawing code 
CGContextRef current_context = UIGraphicsGetCurrentContext();
CGContextSaveGState(current_context);

// Gradient
CGFloat locations[3] = {0.0, 0.5, 1.0};
CGFloat components[12] = {1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0};
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorspace, components, locations, 3);
CGPoint startPoint = CGPointMake(0, 0);
CGPoint endPoint = CGPointMake(40, 40);
CGContextDrawLinearGradient(current_context, gradient, startPoint, endPoint, 0);


// Shadow
CGContextSetShadow(current_context, CGSizeMake(4,7), 1.0);

// Image
UIImage *logoImage = [UIImage imageNamed:@"logo.png"];
[logoImage drawInRect:bounds];
CGContextRestoreGState(current_context);

}

提前感谢您的帮助..

【问题讨论】:

  • 我不希望你得到一个正方形,但我希望你得到渐变。你在看什么你不明白?你能发布一张你得到的和你预期的对比的图片吗?

标签: objective-c cgcontext cgcontextref


【解决方案1】:

您的大部分代码都还可以;问题出现在以下几行:

CGPoint startPoint = CGPointMake(0, 0);
CGPoint endPoint = CGPointMake(40, 40);
CGContextDrawLinearGradient(current_context, gradient, startPoint, endPoint, 0);

CGContextDrawLinearGradient 期望获得起点和终点(定义线,而不是正方形的两条对角线!)。

然后通过与该控制线垂直的彩色线绘制渐变。绘图以使用起始颜色(位置 0 处的颜色)通过 startPoint(垂直于 startPoint 和 endPoint 之间的线)的线开始。下一条线是通过更接近 endPoint 的点“一个像素”绘制的,颜色计算为介于开始和结束或下一个颜色之间的某个位置(取决于颜色位置的数量)。最后,使用结束颜色通过端点(再次垂直...)绘制一条线。

使用(控制)线而不是正方形的优点是,可以在任何方向上绘制渐变;水平,垂直,介于两者之间,仅取决于给定线的方向。

在您的示例代码中,渐变应该是对角线,因为您的线与 x 轴的夹角为 45° :-)。

【讨论】:

  • 为了扩展你所说的,渐变的“形状”,当没有指定选项时,是无限条。它是由您描述的所有虚构的无限长垂直线定义的平面截面。如果指定了.DrawsBeforeStartLocation.DrawsAfterEndLocation,则它是一个半平面。如果两者都指定,则为整个平面。此外,起点和终点不必在上下文的“边界”内。它们可以在任何地方,渐变只会被剪裁到实际的绘图目标。
【解决方案2】:

来自raywanderlich tutorial的代码

override func drawRect(rect: CGRect) {

  //2 - get the current context
  let context = UIGraphicsGetCurrentContext()
  let colors = [startColor.CGColor, endColor.CGColor]

  //3 - set up the color space
  let colorSpace = CGColorSpaceCreateDeviceRGB()

  //4 - set up the color stops
  let colorLocations:[CGFloat] = [0.0, 1.0]

  //5 - create the gradient
  let gradient = CGGradientCreateWithColors(colorSpace, 
                                            colors, 
                                            colorLocations)

  //6 - draw the gradient
  var startPoint = CGPoint.zeroPoint
  var endPoint = CGPoint(x:0, y:self.bounds.height)
  CGContextDrawLinearGradient(context, 
                              gradient, 
                              startPoint, 
                              endPoint, 
                              0)
}

【讨论】: