使用iOS上的CGContext在渐变中绘制线条

时间:2014-10-14 13:34:36

标签: objective-c gradient cgcontext polyline

我正在寻找一种方法,使用CGContextRef沿着它的路径绘制一条线性渐变线。我已经尝试了几种方法,但大多数都专注于用渐变填充区域(rect),这不是我需要的。

我使用以下代码使用CGPathRef绘制实线。我真正需要的是一个平滑的线性渐变,从第一行的color1开始,到行的最后一点以color2结束。

有谁知道如何实现这个目标?

- (CGMutablePathRef)generatedPath
{
    CGMutablePathRef path = CGPathCreateMutable();

    CGPathMoveToPoint(path, nil, 20, 10);
    CGPathAddLineToPoint(path, nil, 100, 100);
    CGPathAddLineToPoint(path, nil, 140, 120);
    CGPathAddLineToPoint(path, nil, 160, 100);
    CGPathAddLineToPoint(path, nil, 210, 70);
    CGPathAddLineToPoint(path, nil, 250, 10);

    return path;
}

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    CGMutablePathRef path = [self generatedPath];
    CGContextAddPath(ctx, path);

    CGColorRef color = [UIColor redColor].CGColor;

    CGContextSetLineWidth(ctx, 8.0);

    CGContextSetStrokeColorWithColor(ctx, color);
    CGContextStrokePath(ctx);
}

======的更新 ============================== ==================

我实际上发现这个问题与我需要的问题非常相似:Gradient Polyline with MapKit ios

我使用以下代码来实现跟随行的路径的渐变。作为评论,不要介意获取和传递路径点的低效方式。我稍后会对此进行优化:

- (NSArray*)generatePathPoints {
    NSMutableArray *points = [[NSMutableArray alloc] init];

    [points addObject:[NSValue valueWithCGPoint:CGPointMake(20, 50)]];
    [points addObject:[NSValue valueWithCGPoint:CGPointMake(100, 100)]];
    [points addObject:[NSValue valueWithCGPoint:CGPointMake(140, 120)]];
    [points addObject:[NSValue valueWithCGPoint:CGPointMake(160, 100)]];
    [points addObject:[NSValue valueWithCGPoint:CGPointMake(210, 70)]];
    [points addObject:[NSValue valueWithCGPoint:CGPointMake(250, 10)]];

    return points;
}

- (CGMutablePathRef)pathFromPoints: (NSArray*)points;
{
    CGMutablePathRef path = CGPathCreateMutable();
    for (int i = 0; i < points.count; i++) {
        NSValue *pointValue = points[i];
        CGPoint point = [pointValue CGPointValue];
        if(i == 0){
            CGPathMoveToPoint(path, nil, point.x, point.y);
        }
        else{
            CGPathAddLineToPoint(path, nil, point.x, point.y);
        }
    }

    return path;
}

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();

    NSArray *points = [self generatePathPoints];

    CGFloat widthOfLine = 8.0;
    CGLineCap lineCap = kCGLineCapRound;
    CGLineJoin lineJoin = kCGLineJoinRound;
    int miterLimit = 10;

    UIColor *ccolor, *pcolor;
    for (int i=0;i< points.count;i++){
        CGMutablePathRef path = CGPathCreateMutable();
        CGPoint point = ((NSValue*)points[i]).CGPointValue;
        ccolor = [self colorForPointAtIndex:i points:points];
        if (i==0){
            CGPathMoveToPoint(path, nil, point.x, point.y);
        } else {
            CGPoint prevPoint = ((NSValue*)points[i-1]).CGPointValue;
            CGPathMoveToPoint(path, nil, prevPoint.x, prevPoint.y);
            CGPathAddLineToPoint(path, nil, point.x, point.y);
            CGFloat pc_r,pc_g,pc_b,pc_a,
            cc_r,cc_g,cc_b,cc_a;
            [pcolor getRed:&pc_r green:&pc_g blue:&pc_b alpha:&pc_a];
            [ccolor getRed:&cc_r green:&cc_g blue:&cc_b alpha:&cc_a];
            CGFloat gradientColors[8] = {pc_r,pc_g,pc_b,pc_a,
                cc_r,cc_g,cc_b,cc_a};

            CGFloat gradientLocation[2] = {0,1};
            CGContextSaveGState(context);
            CGFloat lineWidth = CGContextConvertSizeToUserSpace(context, (CGSize){widthOfLine,widthOfLine}).width;
            CGPathRef pathToFill = CGPathCreateCopyByStrokingPath(path, NULL, lineWidth, lineCap, lineJoin, miterLimit);
            CGContextAddPath(context, pathToFill);
            CGContextClip(context);//<--clip your context after you SAVE it, important!
            CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
            CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, gradientColors, gradientLocation, 2);
            CGColorSpaceRelease(colorSpace);
            CGPoint gradientStart = prevPoint;
            CGPoint gradientEnd = point;
            CGContextDrawLinearGradient(context, gradient, gradientStart, gradientEnd, kCGGradientDrawsAfterEndLocation | kCGGradientDrawsBeforeStartLocation);
            CGGradientRelease(gradient);
            CGContextRestoreGState(context);//<--Don't forget to restore your context.
        }
        pcolor = [UIColor colorWithCGColor:ccolor.CGColor];
    }
}

-(UIColor*) colorForPointAtIndex: (NSUInteger)index points:(NSArray*)points {
    return [UIColor colorWithRed:1.0 green:0 blue:0 alpha:(1.0 / points.count) * index];
}

这会产生我需要的几乎所有。虽然只有微小的故障: http://imgur.com/gn0JE5z

正如您所看到的那样,行结尾是重叠的,这通常不会成为问题。但由于线条透明,我得到了这种不必要的副作用。

有人知道怎么离开这里吗?

0 个答案:

没有答案