如何使用渐变填充UIBezierPath?

时间:2014-04-21 17:18:52

标签: ios uibezierpath

我使用UIBezierPath绘制了一个图表。我可以使用纯色填充图表下方的区域,但我想用渐变而不是纯色填充图表下方的区域。但我不确定如何使渐变仅适用于图表而不适用于整个视图,我已经阅读了一些问题,但未找到任何适用的问题。

enter image description here

这是主要的图形绘制代码:

// Draw the graph
UIBezierPath *barGraph = [UIBezierPath bezierPath];
barGraph.lineWidth = 1.0f;
[blueColor setStroke];
TCDataPoint *dataPoint = self.testData[0];
CGFloat x = [self convertTimeToXPoint:dataPoint.time];
CGFloat y = [self convertDataToYPoint:dataPoint.dataUsage];
CGPoint plotPoint = CGPointMake(x,y);
[barGraph moveToPoint:plotPoint];
for (int ii = 1; ii < [self.testData count]; ++ii)
{
    dataPoint = self.testData[ii];
    x = [self convertTimeToXPoint:dataPoint.time];
    y = [self convertDataToYPoint:dataPoint.dataUsage];
    plotPoint = CGPointMake(x, y);
    [barGraph addLineToPoint:plotPoint];
}
[barGraph stroke];

我一直试图通过尝试以下代码来填充图表,但老实说,尽管经过了各种教程和文档,但我并不确定我做了什么:

[barGraph closePath];

CGFloat colors [] = {
    1.0, 0.0, 0.0, 1.0,
    1.0, 1.0, 1.0, 1.0
};

CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents(baseSpace, colors, NULL, 2);
CGColorSpaceRelease(baseSpace);

CGPoint startPoint = CGPointMake(CGRectGetMidX(self.bounds), self.topY);
CGPoint endPoint = CGPointMake(CGRectGetMidX(self.bounds), self.bottomY);

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClip(context);
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
CGGradientRelease(gradient);

1 个答案:

答案 0 :(得分:11)

最简单的方法是使用原始图形贝塞尔曲线路径来帮助您构建蒙版并将此蒙版强加到渐变图层上。现在将图层设置在渐变图层的顶部。

因此,例如,创建一个CAShapeLayer,关闭图形bezier路径,将其路径设置为形状图层的路径,并将其填充为黑色。现在你有一个掩码,它是图形下面积的形状。现在创建一个CAGradientLayer并使CAShapeLayer成为mask。在此之前,放置实际图表。

例如( EDITED ):

enter image description here

这是我用来创建绘图的代码(我的bezier路径非常简单,只有四个点由三条线连接,但你可以清楚地看到它下面的区域是一个渐变):

CAShapeLayer* shape = [[CAShapeLayer alloc] init];
shape.frame = self.graph.bounds;
CGFloat h = shape.frame.size.height;
CGFloat w = shape.frame.size.width;

NSArray* points = @[
                    [NSValue valueWithCGPoint:CGPointMake(0,h-50)],
                    [NSValue valueWithCGPoint:CGPointMake(70,h-100)],
                    [NSValue valueWithCGPoint:CGPointMake(140,h-75)],
                    [NSValue valueWithCGPoint:CGPointMake(w,h-150)],
                    ];

UIBezierPath* p = [UIBezierPath new];
[p moveToPoint:[points[0] CGPointValue]];
for (NSInteger i = 1; i < points.count; i++)
    [p addLineToPoint:[points[i] CGPointValue]];

shape.path = p.CGPath;
shape.strokeColor = [UIColor blackColor].CGColor;
shape.lineWidth = 2;
shape.fillColor = nil;

CAGradientLayer* grad = [[CAGradientLayer alloc] init];
grad.frame = self.graph.bounds;
grad.colors = @[(id)[UIColor blueColor].CGColor,
                (id)[UIColor yellowColor].CGColor];

CAShapeLayer* mask = [[CAShapeLayer alloc] init];
mask.frame = self.graph.bounds;
[p addLineToPoint:CGPointMake(w,h)];
[p addLineToPoint:CGPointMake(0,h)];
[p closePath];
mask.path = p.CGPath;
mask.fillColor = [UIColor blackColor].CGColor;
grad.mask = mask;

[self.graph.layer addSublayer:grad];
[self.graph.layer addSublayer:shape];