color iphone core-graphics quartz-graphics gradient cashapelayer

iphone - color - swift gradient background



Aplicar un degradado a CAShapeLayer (3)

Esta es una gran solución, pero puede encontrar problemas inesperados si está creando una categoría en CAShapeLayer donde no tiene la vista inmediatamente.

Consulte Configuración del marco correcto de CAShapeLayer recién creado

En la línea inferior, obtenga los límites de la ruta, establezca el marco de la máscara de degradado usando los límites de la ruta y traduzca según sea necesario. Lo bueno es que al usar los límites de la ruta en lugar de cualquier otro marco, el gradiente solo se ajustará a los límites de la ruta (suponiendo que eso es lo que quieres).

// Category on CAShapeLayer CGRect pathBounds = CGPathGetBoundingBox(self.path); CAShapeLayer *gradientMask = [CAShapeLayer layer]; gradientMask.fillColor = [[UIColor blackColor] CGColor]; gradientMask.frame = CGRectMake(0, 0, pathBounds.size.width, pathBounds.size.height); gradientMask.path = self.path; CAGradientLayer *gradientLayer = [CAGradientLayer layer]; gradientLayer.startPoint = CGPointMake(0.5,1.0); gradientLayer.endPoint = CGPointMake(0.5,0.0); gradientLayer.frame = CGRectMake(0, 0, pathBounds.size.width, pathBounds.size.height); NSMutableArray *colors = [NSMutableArray array]; for (int i = 0; i < 10; i++) { [colors addObject:(id)[[UIColor colorWithHue:(0.1 * i) saturation:1 brightness:.8 alpha:1] CGColor]]; } gradientLayer.colors = colors; [gradientLayer setMask:gradientMask]; [self addSublayer:gradientLayer];

¿Alguien tiene alguna experiencia en aplicar un degradado a un CAShapeLayer? CAShapeLayer es una clase de capa fantástica, pero parece que solo es compatible con la coloración de relleno sólido, mientras que me gustaría que tuviera un relleno de degradado (en realidad, un degradado animable).

Todo lo que tiene que ver con CAShapeLayer (sombras, formas, color de trazo, ruta de forma animable) es fantástico.

He intentado colocar un CAGradientLayer dentro de un CAShapeLayer, o incluso establecer el CAShapeLayer como la máscara del GradientLayer y agregar ambos a una capa de contenedor, pero estos no tienen el resultado correcto.

¿Debo subclasificar CAShapeLayer o hay una mejor manera de avanzar?

Gracias.


Muchas gracias a @Palimondo por una gran respuesta!

En caso de que alguien esté buscando el código de animación Swift 4 + fill de esta solución:

let myView = UIView(frame: .init(x: 0, y: 0, width: 200, height: 150)) view.addSubview(myView) myView.center = view.center // Start and finish point let startPoint = CGPoint(x: myView.bounds.minX, y: myView.bounds.midY) let finishPoint = CGPoint(x: myView.bounds.maxX, y: myView.bounds.midY) // Path let path = UIBezierPath() path.move(to: startPoint) path.addLine(to: finishPoint) // Gradient Mask let gradientMask = CAShapeLayer() let lineHeight = myView.frame.height gradientMask.fillColor = UIColor.clear.cgColor gradientMask.strokeColor = UIColor.black.cgColor gradientMask.lineWidth = lineHeight gradientMask.frame = myView.bounds gradientMask.path = path.cgPath // Gradient Layer let gradientLayer = CAGradientLayer() gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5) gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5) // make sure to use .cgColor gradientLayer.colors = [UIColor.red.cgColor, UIColor.green.cgColor] gradientLayer.frame = myView.bounds gradientLayer.mask = gradientMask myView.layer.addSublayer(gradientLayer) // Corner radius myView.layer.cornerRadius = 10 myView.clipsToBounds = true

Extra . En caso de que también necesite una "animación de relleno", agregue estas líneas:

// Filling animation let animation = CABasicAnimation(keyPath: "strokeEnd") animation.fromValue = 0 animation.duration = 10 gradientMask.add(animation, forKey: "LineAnimation")


Podría usar la ruta de su forma para crear una capa de enmascaramiento y aplicarla en la capa de degradado, así:

UIView *v = [[UIView alloc] initWithFrame:self.window.frame]; CAShapeLayer *gradientMask = [CAShapeLayer layer]; gradientMask.fillColor = [[UIColor clearColor] CGColor]; gradientMask.strokeColor = [[UIColor blackColor] CGColor]; gradientMask.lineWidth = 4; gradientMask.frame = CGRectMake(0, 0, v.bounds.size.width, v.bounds.size.height); CGMutablePathRef t = CGPathCreateMutable(); CGPathMoveToPoint(t, NULL, 0, 0); CGPathAddLineToPoint(t, NULL, v.bounds.size.width, v.bounds.size.height); gradientMask.path = t; CAGradientLayer *gradientLayer = [CAGradientLayer layer]; gradientLayer.startPoint = CGPointMake(0.5,1.0); gradientLayer.endPoint = CGPointMake(0.5,0.0); gradientLayer.frame = CGRectMake(0, 0, v.bounds.size.width, v.bounds.size.height); NSMutableArray *colors = [NSMutableArray array]; for (int i = 0; i < 10; i++) { [colors addObject:(id)[[UIColor colorWithHue:(0.1 * i) saturation:1 brightness:.8 alpha:1] CGColor]]; } gradientLayer.colors = colors; [gradientLayer setMask:gradientMask]; [v.layer addSublayer:gradientLayer];

Si también desea utilizar las sombras, tendría que colocar un "duplicado" de la capa de forma debajo de la capa de degradado, reciclando la misma referencia de ruta.