【问题标题】:Draw gradient along a curved UIBezierPath沿着弯曲的 UIBezierPath 绘制渐变
【发布时间】:2013-12-17 11:00:14
【问题描述】:

在一个应用程序中,我绘制了一个弯曲的 UIBezierPath 和一个 MKOverlayPathView 类来显示飞行路线。这是我正在使用的代码:

- (UIBezierPath *)pathForOverlayForMapRect:(MKMapRect)mapRect {

    ... bla bla bla ...

    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:s];
    [path addQuadCurveToPoint:e controlPoint:cp1];
    [path addLineToPoint:e2];
    [path addQuadCurveToPoint:s2 controlPoint:cp2];
    [path closePath];

    return path;   
  }
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context{

    self.mapRect = mapRect;

    CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
    CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);
    CGContextSetLineWidth(context, mapRect.size.height/700);
    CGContextSetLineJoin(context, kCGLineJoinRound);
    CGContextSetLineCap(context, kCGLineCapRound);

    CGContextAddPath(context, [self pathForOverlayForMapRect:mapRect].CGPath);

    [self updateTouchablePathForMapRect:mapRect];

    CGContextDrawPath(context, kCGPathFillStroke);

}

这工作得很好,但我想沿着该路径绘制一个渐变,而不仅仅是填充颜色。这就是它开始变得非常棘手的地方。

我已经尝试过 CGContextDrawLinearGradient(),但它还没有让我有任何用处。

【问题讨论】:

    标签: ios objective-c gradient uibezierpath


    【解决方案1】:

    诀窍是使用线条的描边路径(CGContextReplacePathWithStrokedPath)并对其进行剪辑(CGContextClip)来限制路径的渐变:

    // Create a gradient from white to red
    CGFloat colors [] = {
        1.0, 1.0, 1.0, 1.0,
        1.0, 0.0, 0.0, 1.0
    };
    
    CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB();
    CGGradientRef gradient = CGGradientCreateWithColorComponents(baseSpace, colors, NULL, 2);
    CGColorSpaceRelease(baseSpace), baseSpace = NULL;
    
    CGContextSetLineWidth(context, mapRect.size.height/700);
    CGContextSetLineJoin(context, kCGLineJoinRound);
    CGContextSetLineCap(context, kCGLineCapRound);
    
    CGContextAddPath(context, [self pathForOverlayForMapRect:mapRect].CGPath);
    CGContextReplacePathWithStrokedPath(context);
    CGContextClip(context);
    
    [self updateTouchablePathForMapRect:mapRect];
    
    // Define the start and end points for the gradient
    // This determines the direction in which the gradient is drawn
    CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
    CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
    
    CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
    CGGradientRelease(gradient), gradient = NULL;
    

    【讨论】:

    • 这个答案很完美!非常感谢你。我删除了CGContextReplacePathWithStrokedPath(),所以我的路径将被渐变填充,而不仅仅是被它勾勒出来。
    • CGContextReplacePathWithStrokedPath 如果您想要渐变沿路径(根据问题)而不是内部路径。跨度>
    • 我在使用“CGContextReplacePathWithStrokedPath”时遇到的问题是渐变只应用于路径本身,但没有填充它。描边而不是填充。还是我做错了什么?
    • @freshking 你沿着渐变沿着询问了一条路径,它是一个笔划。至少现在您知道如何进行渐变笔触和填充了 :)
    • 如果我错了,请纠正我,但这不会沿路径应用渐变,而是使用路径作为一种千篇一律的切割器来获取线性渐变的一部分。渐变实际上遵循一条直线路径。有没有办法将渐变应用于路径。为了说明我的意思,假设路径是一个循环,以白色开头,结尾为黑色。不同之处在于线性渐变会导致路径变暗,然后通过循环再次变亮,然后再变暗到最后。沿路径的渐变将从白色开始,到最后变为黑色。
    【解决方案2】:

    在 Swift 3 中,这可以使用下面的代码来实现。此示例适用于直线,但应适用相同的原则。

        let startPoint = CGPoint(x:100, y:100)
        let endPoint = CGPoint(x: 300, y:400)
    
        let context = UIGraphicsGetCurrentContext()!
        context.setStrokeColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0);
        // create a line
        context.move(to: startPoint)
        context.addLine(to: endPoint)
        context.setLineWidth(4)
        // use the line created above as a clipping mask
        context.replacePathWithStrokedPath()
        context.clip()
    
        // create a gradient
        let locations: [CGFloat] = [ 0.0, 0.5 ]
    
        let colors = [UIColor.green.cgColor,
                      UIColor.white.cgColor]
    
        let colorspace = CGColorSpaceCreateDeviceRGB()
    
        let gradient = CGGradient(colorsSpace: colorspace,
                                  colors: colors as CFArray, locations: locations)
    
        let gradientStartPoint = CGPoint(x: rect.midX, y: rect.minY)
        let gradientEndPoint = CGPoint(x: rect.midX, y: rect.maxY)
    
        context.drawLinearGradient(gradient!,
                                    start: gradientStartPoint, end: gradientEndPoint,
                                    options: .drawsBeforeStartLocation)
        UIGraphicsEndImageContext()
    

    【讨论】:

      猜你喜欢
      • 2014-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-28
      • 2018-09-10
      • 1970-01-01
      • 1970-01-01
      • 2018-01-26
      相关资源
      最近更新 更多