2013-12-17 28 views
16

アプリでは、曲線のUIBezierPathをMKOverlayPathViewクラスで描き、飛行ルートを表示します。これは私が使用していたコードです:これはうまく機能していますが、私だけではなく、塗りつぶしの色のそのパスに沿ってグラデーションを描きたいと思い湾曲したUIBezierPathに沿ってグラデーションを描く

- (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()を実験しましたが、まだ役に立たなかったことがあります。

答えて

23

トリックライン(CGContextReplacePathWithStrokedPath)のストロークパスを使用し、(CGContextClip)を、それをクリップパスに勾配を制限することである:スウィフト3において

// 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; 
+0

この回答は完璧です!どうもありがとうございました。 'CGContextReplacePathWithStrokedPath()'を削除しました。私のパスはグラデーションで塗りつぶされ、輪郭線だけではありません。 – freshking

+0

'CGContextReplacePathWithStrokedPath'は、パスの代わりにパス(質問単位)をグラントしたい場合に便利です。 – neilco

+0

私が 'CGContextReplacePathWithStrokedPath'で得ていた問題は、グラデーションがパス自体にのみ適用されていて、それを塗りつぶさなかったことでした。塗りの代わりにストローク。それとも、何か間違ったことがありましたか? – freshking

0

これは以下のコードを使用して達成することができます。この例は直線ですが、同じ原則が適用されるはずです。

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() 
関連する問題