ios objective-c calayer quartz-core

ios - ¿Cómo dibujar degradados radiales en un CALayer?



objective-c quartz-core (3)

Sé que CAGradientLayer no admite gradiente radial en este momento y solo tiene la opción de kCAGradientLayerAxial .

Quiero algo como a continuación:

He mirado a mi alrededor para este problema y he encontrado que hay una manera de evitar esto. Pero las explicaciones no fueron claras para mí. Entonces, quiero saber si puedo dibujar gradientes radiales usando CAGradientLayer y, de ser así, ¿cómo hacerlo?


Aquí está el código Swift3 que utilizo:

import UIKit class RadialGradientLayer: CALayer { required override init() { super.init() needsDisplayOnBoundsChange = true } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } required override init(layer: Any) { super.init(layer: layer) } public var colors = [UIColor.red.cgColor, UIColor.blue.cgColor] override func draw(in ctx: CGContext) { ctx.saveGState() let colorSpace = CGColorSpaceCreateDeviceRGB() var locations = [CGFloat]() for i in 0...colors.count-1 { locations.append(CGFloat(i) / CGFloat(colors.count)) } let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: locations) let center = CGPoint(x: bounds.width / 2.0, y: bounds.height / 2.0) let radius = min(bounds.width / 2.0, bounds.height / 2.0) ctx.drawRadialGradient(gradient!, startCenter: center, startRadius: 0.0, endCenter: center, endRadius: radius, options: CGGradientDrawingOptions(rawValue: 0)) } }


No sé cuándo, pero ahora puede cambiar el type de kCAGradientLayerRadial a kCAGradientLayerRadial y funciona.

En teoría, el rendimiento de Core Animation es mejor que Core Graphics.

Algún código de ejemplo:

class View : UIView { let gradientLayer = CAGradientLayer() override init(frame: CGRect) { super.init(frame: frame) gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.5) gradientLayer.endPoint = CGPoint(x: 1, y: 1) gradientLayer.locations = [ NSNumber(value: 0.6), NSNumber(value: 0.8) ] gradientLayer.type = .radial gradientLayer.colors = [ UIColor.green.cgColor, UIColor.purple.cgColor, UIColor.orange.cgColor, UIColor.red.cgColor ] self.layer.addSublayer(gradientLayer) } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override func layoutSublayers(of layer: CALayer) { assert(layer === self.layer) gradientLayer.frame = layer.bounds } }


Por lo que entendí, solo necesita una capa que dibuje un gradiente, y CGContextDrawRadialGradient funciona perfectamente para esa necesidad. Y para reiterar sobre lo que dijo, CAGradientLayer no admite gradientes radiales, y no podemos hacer nada al respecto, excepto los movimientos innecesarios que se pueden realizar de manera limpia con una subclase CALayer .

( nota: el código de dibujo de gradiente se tomó de aquí . No es de lo que trata esta respuesta ) .

viewDidLoad :

GradientLayer *gradientLayer = [[GradientLayer alloc] init]; gradientLayer.frame = self.view.bounds; [self.view.layer addSublayer:gradientLayer];

Subclase CALayer :

- (instancetype)init { self = [super init]; if (self) { [self setNeedsDisplay]; } return self; } - (void)drawInContext:(CGContextRef)ctx { size_t gradLocationsNum = 2; CGFloat gradLocations[2] = {0.0f, 1.0f}; CGFloat gradColors[8] = {0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.5f}; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, gradColors, gradLocations, gradLocationsNum); CGColorSpaceRelease(colorSpace); CGPoint gradCenter= CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); CGFloat gradRadius = MIN(self.bounds.size.width , self.bounds.size.height) ; CGContextDrawRadialGradient (ctx, gradient, gradCenter, 0, gradCenter, gradRadius, kCGGradientDrawsAfterEndLocation); CGGradientRelease(gradient); }