2009-08-20 115 views
22

我知道如何绘制简单的线条:如何使用Core Graphics/iPhone绘制渐变线(淡入/淡出)?

CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); 
CGContextMoveToPoint(context, x, y); 
CGContextAddLineToPoint(context, x2, y2); 
CGContextStrokePath(context); 

而且我知道如何做一个渐变的矩形,i.g:

CGColorSpaceRef myColorspace=CGColorSpaceCreateDeviceRGB(); 
size_t num_locations = 2; 
CGFloat locations[2] = { 1.0, 0.0 }; 
CGFloat components[8] = { 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; 

CGGradientRef myGradient = CGGradientCreateWithColorComponents(myColorspace, components, locations, num_locations); 

CGPoint myStartPoint, myEndPoint; 
myStartPoint.x = 0.0; 
myStartPoint.y = 0.0; 
myEndPoint.x = 0.0; 
myEndPoint.y = 10.0; 
CGContextDrawLinearGradient (context, myGradient, myStartPoint, myEndPoint, 0); 

但我怎么能画一条线的渐变,胃内从黑色渐变为白色(也可能在另一侧渐渐变黑)?

+1

快速注释 - 此处选择的答案不正确。 **这是可能的笔画任意路径与梯度**作为[这个答案](http://stackoverflow.com/a/25034854/2547229)显示。 – Benjohn 2015-05-22 12:48:26

回答

20

经过多次尝试后,我现在确定渐变不会影响笔画,所以我认为不可能使用CGContextStrokePath()绘制渐变线。对于水平线和垂直线,解决方案是使用CGContextAddRect(),幸运的是我需要的。我换成

CGContextMoveToPoint(context, x, y); 
CGContextAddLineToPoint(context, x2, y2); 
CGContextStrokePath(context); 

CGContextSaveGState(context); 
CGContextAddRect(context, CGRectMake(x, y, width, height)); 
CGContextClip(context); 
CGContextDrawLinearGradient (context, gradient, startPoint, endPoint, 0); 
CGContextRestoreGState(context); 

,一切工作正常。感谢Brad Larson提供的关键提示。

+0

我发现了完全一样的东西。它会出现渐变需要一个剪辑路径(或矩形)首先应用于图形上下文。也许这是因为渐变渲染在封闭区域而不是路径(或矩形)边界本身? – Dalmazio 2011-07-29 14:51:17

+0

这不能显示斜坡线? – AntiMoron 2016-03-17 03:24:07

8

您可以使用Core Animation图层。您可以通过设置其路径属性来为您的线使用CAShaperLayer,然后您可以使用CAGradientLayer作为图层蒙版到您的形状图层,这将导致线条消失。

将您的CGContext ...调用替换为调用CGPath ...调用以创建行路径。使用该路径在图层上设置路径字段。然后在您的梯度层,指定要使用的(可能是黑到白)的颜色,然后将面膜是线层是这样的:

[gradientLayer setMask:lineLayer]; 

什么是很酷的梯度层是允许你指定渐变将停止的位置列表,以便您可以淡入和淡出。它只支持线性渐变,但听起来可能符合您的需求。

让我知道你是否需要澄清。

编辑:现在,我想起它,只需创建一个单一的CAGradientLayer,即您想要的线条的宽度/高度。指定渐变颜色(黑色至白色或黑色以清除颜色)以及startPoint和endtPoints,它应该为您提供所需的内容。

+0

你说得对,这完全符合我的需求,但不幸的是,这只适用于iPhone OS 3的版本,我想至少使用2.2。不管怎么说,还是要谢谢你... – Walchy 2009-08-20 15:54:06

+1

我想你的意思是[gradientLayer setMask:LineLayer]; - 对?您用CAShapeLayer遮罩CAGradientLayer。 – Palimondo 2011-08-19 21:39:00

+0

辉煌。学到了很多。 – Ian1971 2011-10-07 19:11:20

8

之后你画的线,你可以调用

CGContextClip(context); 

进一步拉夹到你的行区域。如果您绘制渐变,它现在应该包含在线区域内。请注意,如果您只想显示渐变,而不是下方的线条,则需要为线条使用清晰的颜色。您可以使用CGContextAddRect()来定义较厚的区域。

我在我的回答here中提供了一个更详细的使用此上下文剪辑的示例。

+1

我试过你的建议: \t CGContextSetLineWidth(context,10.0); //应该足够厚 \t CGContextSetRGBStrokeColor(context,0.0,0.0,0.0,0.0); \t CGContextMoveToPoint(context,50,50); \t CGContextAddLineToPoint(context,100,100); \t CGContextStrokePath(context); \t CGContextClip(context); \t CGContextDrawLinearGradient(context,myGradient,myStartPoint,myEndPoint,0); 但这抛出 :doClip:空路径。 该文档说, CGContextStrokePath(context); 清除路径 - 没有这个方法没有错误被抛出,但没有任何东西被绘制。 任何想法? – Walchy 2009-08-20 16:04:23

0
CGContextMoveToPoint(context, frame.size.width-200, frame.origin.y+10); 
CGContextAddLineToPoint(context, frame.size.width-200, 100-10); 
CGFloat colors[16] = { 0,0, 0, 0, 
    0, 0, 0, .8, 
    0, 0, 0, .8, 
    0, 0,0 ,0 }; 
CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB(); 
CGGradientRef gradient = CGGradientCreateWithColorComponents(baseSpace, colors, NULL, 4); 

CGContextSaveGState(context); 
CGContextAddRect(context, CGRectMake(frame.size.width-200,10, 1, 80)); 
CGContextClip(context); 
CGContextDrawLinearGradient (context, gradient, CGPointMake(frame.size.width-200, 10), CGPointMake(frame.size.width-200,80), 0); 
CGContextRestoreGState(context); 

它为我工作。

25

是可能的中风任意路径用梯度,或者任何其它填充效果,诸如图案。

正如你已经发现,描边路径不与当前的渐变渲染。这只充满路径使用渐变(当你打开他们的剪辑,然后绘制渐变)。

然而,核芯显卡有一个惊人的冷静程序CGContextReplacePathWithStrokedPath将在改变你打算路径行程到是相当于装满时的路径。

在幕后,CGContextReplacePathWithStrokedPath构建了一个多边形边缘周围的描边路径和交换机的路径已定义。我推测,核心图形渲染引擎可能在调用CGContextStrokePath做到这一点反正

下面是关于这款苹果的文档:

石英创建使用当前图形上下文的参数描边路径。创建新的路径,以便填充它绘制相同的像素作为抚摸着原始路径。您可以像使用任何上下文的路径一样使用此路径。例如,可以通过调用这个函数,然后在函数CGContextClip调用剪辑的路径描边版本。

所以,在转换的东西,你可以填写你的路径,转而在一个剪辑,然后的梯度。效果就好像你已经用渐变抚摸了路径。

代码

它会是这个样子......

// Get the current graphics context. 
    // 
    const CGContextRef context = UIGraphicsGetCurrentContext(); 

    // Define your stroked path. 
    // 
    // You can set up **anything** you like here. 
    // 
    CGContextAddRect(context, yourRectToStrokeWithAGradient); 

    // Set up any stroking parameters like line. 
    // 
    // I'm setting width. You could also set up a dashed stroke 
    // pattern, or whatever you like. 
    // 
    CGContextSetLineWidth(context, 1); 

    // Use the magical call. 
    // 
    // It turns your _stroked_ path in to a **fillable** one. 
    // 
    CGContextReplacePathWithStrokedPath(context); 

    // Use the current _fillable_ path in to define a clipping region. 
    // 
    CGContextClip(context); 

    // Draw the gradient. 
    // 
    // The gradient will be clipped to your original path. 
    // You could use other fill effects like patterns here. 
    // 
    CGContextDrawLinearGradient(
     context, 
     yourGradient, 
     gradientTop, 
     gradientBottom, 
     0 
    ); 

还注意到

值得强调上述文件的一部分:

石英创建描边路径使用当前图形上下文的参数。

明显的参数是线宽。但是,所有都使用了线条绘制状态,例如笔画图案,斜接限制,线条连接,上限,破折号图案等。这使得该方法非常强大。

欲了解更多详情,请参阅this answerthis S.O. question