ovalin example ios objective-c gradient uibezierpath

ios - example - Dibujar un gradiente a lo largo de una curva UIBezierPath



uibezierpath ovalin (2)

En una aplicación, dibujo un UIBezierPath curvo y una clase MKOverlayPathView para mostrar las rutas de vuelo. Este es el código que estoy usando:

- (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); }

Esto está funcionando bien, pero me gustaría dibujar un degradado a lo largo de ese camino en lugar de solo un color de relleno. Y aquí es donde empieza a ser muy complicado.

He experimentado con CGContextDrawLinearGradient () pero todavía no me ha servido de nada.


El truco es usar la ruta de trazo de la línea ( CGContextReplacePathWithStrokedPath ) y recortarla ( CGContextClip ) para restringir el gradiente a la ruta:

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


En Swift 3, esto se puede lograr usando el siguiente código. Este ejemplo es para una línea recta, pero deben aplicarse los mismos principios.

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()