我一直在撞墙,试图弄清楚为什么这不起作用。
基本上,我试图使用CGPath绘制图形(图表),然后使用它来剪切渐变。最终效果应该像iPhone附带的Stocks应用程序一样。
渐变和路径分别作为两个分层(未剪切)元素精细绘制。但是如果我注释掉CGContextDrawPath,那么行和渐变都不会绘制到屏幕上。
这是我的drawRect代码:
CGContextRef context = UIGraphicsGetCurrentContext();
[[UIColor whiteColor] set];
CGContextSetLineWidth(context, 2.0f);
CGPoint lastDrawnPt = [[points objectAtIndex:0] CGPointValue];
CGPoint firstDrawnPt = lastDrawnPt;
//create the path for the gradient
CGMutablePathRef thePath = CGPathCreateMutable();
CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, self.bounds.size.height); // bottom left
CGPathAddLineToPoint(thePath, NULL, lastDrawnPt.x, lastDrawnPt.y);
for (int i=0; i<(points.count-1); i++) {
//CGPoint pt1 = [[points objectAtIndex:i] CGPointValue];
CGPoint pt2 = [[points objectAtIndex:i+1] CGPointValue];
if (pt2.x > lastDrawnPt.x+2) {
// only draw if we've moved sunstantially to the right
//for the gradient
CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, lastDrawnPt.y);
CGPathAddLineToPoint(thePath, NULL, pt2.x, pt2.y);
lastDrawnPt = pt2;
}
}
//finish the gradient clipping path
CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, lastDrawnPt.y);
CGPathAddLineToPoint(thePath, NULL, lastDrawnPt.x, self.bounds.size.height); // bottom right
CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, self.bounds.size.height);
CGPathAddLineToPoint(thePath, NULL, firstDrawnPt.x, self.bounds.size.height); // bottom right
CGPathCloseSubpath(thePath);
//add the gradient clipping path to the context
CGContextSaveGState(context);
CGContextAddPath(context, thePath);
//draw the path
float components[4] = {1.0, 1.0, 1.0, 1.0};
CGContextSetStrokeColor(context, components);
CGContextDrawPath(context,kCGPathStroke);
//clip the path
CGContextClip(context);
//Draw Gradient
UIColor *topColor = [UIColor colorWithRed: 1.0 green:1.0 blue:1.0 alpha:1.0];
UIColor *bottomColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.0];
CGColorRef colorRef[] = { [topColor CGColor], [bottomColor CGColor] };
CFArrayRef colors = CFArrayCreate(NULL, (const void**)colorRef, sizeof(colorRef) / sizeof(CGColorRef), &kCFTypeArrayCallBacks);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, colors, NULL);
CFRelease(colorSpace);
CFRelease(colors);
// Draw a linear gradient from top to bottom
CGPoint gradStartPoint = CGPointMake(50.0, self.bounds.size.height);
CGPoint gradEndPoint = CGPointMake(50.0, 0.0);
CGContextDrawLinearGradient(context, gradient, gradStartPoint, gradEndPoint, 0);
CFRelease(gradient);
// Cleanup
CGColorSpaceRelease(colorSpace);
CGContextRestoreGState(context);
答案 0 :(得分:1)
CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, self.bounds.size.height); // bottom left CGPathAddLineToPoint(thePath, NULL, lastDrawnPt.x, lastDrawnPt.y); for (int i=0; i<(points.count-1); i++) { //CGPoint pt1 = [[points objectAtIndex:i] CGPointValue]; CGPoint pt2 = [[points objectAtIndex:i+1] CGPointValue]; if (pt2.x > lastDrawnPt.x+2) { // only draw if we've moved sunstantially to the right //for the gradient CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, lastDrawnPt.y); CGPathAddLineToPoint(thePath, NULL, pt2.x, pt2.y); lastDrawnPt = pt2; } } //finish the gradient clipping path CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, lastDrawnPt.y); CGPathAddLineToPoint(thePath, NULL, lastDrawnPt.x, self.bounds.size.height); // bottom right CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, self.bounds.size.height); CGPathAddLineToPoint(thePath, NULL, firstDrawnPt.x, self.bounds.size.height); // bottom right
这只是绘制了一系列线段。对于某些点值,它可能看起来像这样:
| |||| |
它不会绘制单个连续形状。因此,这条路径对于剪切是无用的,因为它实际上是空的;正如您所见,剪切到它将导致剪切路径内没有进一步的绘图。
每个lineto
,curveto
,arc
等等都是从当前点开始的。您使用moveto
设置最初,但每个lineto
,curveto
,arc
等都不会清除当前点,它更新它。因此,要创建单个形状,请执行一个moveto
后跟一系列lineto
(或curveto
或arc
),最后是closepath
。
说到closepath
......
CGPathCloseSubpath(thePath);
这会在路径中创建唯一的闭合形状,但由于该形状的区域为零(只是一个自身加倍的线段),因此它仍然无法用于剪切目的。
我怀疑你需要做的就是至少删除一个moveto
段(循环中的一段,如果不是那么后面的那段)。然后,您可以简化数组上的循环使用快速枚举,而不是使用索引,并切断跟踪“最后绘制的点”。
此外,NSArray索引的正确类型是NSUInteger
,而不是int
。保持你的类型匹配 - 它可以避免后来的痛苦。