如何将CAGradientLayer添加到CAShapeLayer?

我正在尝试将CAGradientLayer添加到CAShapeLayer,但渐变不符合图层的形状。 相反,渐变呈现出UIView本身的形状。 我最初尝试使用UIBezierPath,但它也没有用。 我试图在我的形状中加入渐变。

override func drawRect(rect: CGRect) { let bounds = CGRect(x: 0, y: 0, width: self.bounds.width, height: self.bounds.height) let center = self.center let path = CAShapeLayer() path.bounds = bounds path.position = CGPoint(x: center.x, y: center.y) //path.backgroundColor = UIColor.redColor().CGColor path.cornerRadius = 20 //self.layer.addSublayer(path) let gradientLayer = CAGradientLayer() gradientLayer.frame = path.bounds gradientLayer.colors = [cgColorForRed(209.0, green: 0.0, blue: 0.0), cgColorForRed(255.0, green: 102.0, blue: 34.0), cgColorForRed(255.0, green: 218.0, blue: 33.0), cgColorForRed(51.0, green: 221.0, blue: 0.0), cgColorForRed(17.0, green: 51.0, blue: 204.0), cgColorForRed(34.0, green: 0.0, blue: 102.0), cgColorForRed(51.0, green: 0.0, blue: 68.0)] gradientLayer.startPoint = CGPoint(x:0,y:0) gradientLayer.endPoint = CGPoint(x:0, y:1) path.insertSublayer(gradientLayer, atIndex: 1) self.layer.addSublayer(path) } func cgColorForRed(red: CGFloat, green: CGFloat, blue: CGFloat ) -> AnyObject { return UIColor(red: red/255.0, green: green/255.0, blue: blue/255.5, alpha: 1.0).CGColor as AnyObject } 

最初我将路径定义为带圆角的矩形的UIBezierPath,我希望用渐变填充:

  let insetRect = CGRectInset(rect, lineWidth / 2, lineWidth / 2) let path = UIBezierPath(roundedRect: insetRect, cornerRadius: 10) fillColor.setFill() path.fill() path.lineWidth = self.lineWidth UIColor.blackColor().setStroke() path.stroke() 

根据Larcerax的回复编辑:

 class Thermometer: UIView { //@IBInspectable var fillColor: UIColor = UIColor.greenColor() let lineWidth: CGFloat = 2 override func drawRect(rect: CGRect) { let context = UIGraphicsGetCurrentContext() let svgid = CGGradientCreateWithColors(CGColorSpaceCreateDeviceRGB(), [cgColorForRed(209.0, green: 0.0, blue: 0.0), cgColorForRed(255.0, green: 102.0, blue: 34.0), cgColorForRed(255.0, green: 218.0, blue: 33.0), cgColorForRed(51.0, green: 221.0, blue: 0.0), cgColorForRed(17.0, green: 51.0, blue: 204.0), cgColorForRed(34.0, green: 0.0, blue: 102.0), cgColorForRed(51.0, green: 0.0, blue: 68.0)], [0,1]) CGContextSaveGState(context) let insetRect = CGRectInset(rect, lineWidth / 2, lineWidth / 2) let path = UIBezierPath(roundedRect: insetRect, cornerRadius: 10) path.addClip() CGContextDrawLinearGradient(context, svgid, CGPoint(x: 0, y: path.bounds.height), CGPoint(x: path.bounds.width, y: path.bounds.height), UInt32(kCGGradientDrawsBeforeStartLocation) | UInt32(kCGGradientDrawsAfterEndLocation)) CGContextRestoreGState(context) } 

您可以尝试类似下面的设置以生成以下形状,这只是一个向您展示设置的示例,但是这应该这样做:

  let context = UIGraphicsGetCurrentContext() let gradientColor3 = UIColor(red: 1.000, green: 1.000, blue: 1.000, alpha: 1.000) let gradientColor4 = UIColor(red: 0.000, green: 1.000, blue: 0.000, alpha: 1.000) let sVGID_1_2 = CGGradientCreateWithColors(CGColorSpaceCreateDeviceRGB(), [gradientColor3.CGColor, gradientColor4.CGColor], [0, 1]) CGContextSaveGState(context) CGContextTranslateCTM(context, 198.95, 199.4) CGContextRotateCTM(context, -30 * CGFloat(M_PI) / 180) var polygonPath = UIBezierPath() polygonPath.moveToPoint(CGPointMake(0, -145.95)) polygonPath.addLineToPoint(CGPointMake(126.4, -72.98)) polygonPath.addLineToPoint(CGPointMake(126.4, 72.97)) polygonPath.addLineToPoint(CGPointMake(0, 145.95)) polygonPath.addLineToPoint(CGPointMake(-126.4, 72.98)) polygonPath.addLineToPoint(CGPointMake(-126.4, -72.97)) polygonPath.closePath() CGContextSaveGState(context) polygonPath.addClip() CGContextDrawLinearGradient(context, sVGID_1_2, CGPointMake(-126.4, -72.97), CGPointMake(126.41, 72.99), UInt32(kCGGradientDrawsBeforeStartLocation) | UInt32(kCGGradientDrawsAfterEndLocation)) CGContextRestoreGState(context) 

产生这个:

在此处输入图像描述

如果这不起作用,那么告诉我,我会尝试修复它以使其工作。

另外,这里只是一个简单的矩形:

 let context = UIGraphicsGetCurrentContext() let gradientColor = UIColor(red: 1.000, green: 1.000, blue: 1.000, alpha: 1.000) let gradientColor2 = UIColor(red: 0.988, green: 0.933, blue: 0.129, alpha: 1.000) let gradientColor3 = UIColor(red: 1.000, green: 0.000, blue: 1.000, alpha: 1.000) let sVGID_1_3 = CGGradientCreateWithColors(CGColorSpaceCreateDeviceRGB(), [gradientColor.CGColor, gradientColor2.CGColor, gradientColor3.CGColor], [0, 0.43, 1]) let rectanglePath = UIBezierPath(rect: CGRectMake(68, 28, 78.4, 78.4)) CGContextSaveGState(context) rectanglePath.addClip() CGContextDrawLinearGradient(context, sVGID_1_3, CGPointMake(68, 67.19), CGPointMake(146.38, 67.19), UInt32(kCGGradientDrawsBeforeStartLocation) | UInt32(kCGGradientDrawsAfterEndLocation)) CGContextRestoreGState(context) 

在此处输入图像描述

这是一个尝试的function,你将不得不搞乱颜色,但你可以输入一个框架:

 class func drawStuff(#frame: CGRect) { let context = UIGraphicsGetCurrentContext() let gradientColor = UIColor(red: 1.000, green: 1.000, blue: 1.000, alpha: 1.000) let gradientColor2 = UIColor(red: 0.988, green: 0.933, blue: 0.129, alpha: 1.000) let gradientColor3 = UIColor(red: 1.000, green: 0.000, blue: 1.000, alpha: 1.000) let sVGID_1_4 = CGGradientCreateWithColors(CGColorSpaceCreateDeviceRGB(), [gradientColor.CGColor, gradientColor2.CGColor, gradientColor3.CGColor], [0, 0.43, 1]) let rectangleRect = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height) let rectanglePath = UIBezierPath(rect: rectangleRect) CGContextSaveGState(context) rectanglePath.addClip() CGContextDrawLinearGradient(context, sVGID_1_4, CGPointMake(rectangleRect.minX, rectangleRect.midY),CGPointMake(rectangleRect.maxX, rectangleRect.midY), 0) CGContextRestoreGState(context) } 

或者您可以使用我自己写的:) https://github.com/BilalReffas/SwiftyGradient

从上面的@Loxx回答的第一个形状的Swift 4版本产生这个输出:

@Loxx造型#1

 private func drawShape() { guard let context = UIGraphicsGetCurrentContext() else { print("No context, handle me") return } let gradientColor3 = UIColor(red: 1.000, green: 1.000, blue: 1.000, alpha: 1.000) let gradientColor4 = UIColor(red: 0.000, green: 1.000, blue: 0.000, alpha: 1.000) guard let sVGID_1_2 = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: [gradientColor3.cgColor, gradientColor4.cgColor] as CFArray, locations: [0, 1]) else { print("No gradient, handle me") context.restoreGState() return } context.saveGState() context.translateBy(x: 198.95, y: 199.4) context.rotate(by: -30 * CGFloat(Double.pi) / 180) let polygonPath = UIBezierPath() polygonPath.move(to: CGPoint(x: 0, y: -145.95)) polygonPath.addLine(to: CGPoint(x: 126.4, y: -72.98)) polygonPath.addLine(to: CGPoint(x: 126.4, y: 72.97)) polygonPath.addLine(to: CGPoint(x: 0, y: 145.95)) polygonPath.addLine(to: CGPoint(x: -126.4, y: 72.98)) polygonPath.addLine(to: CGPoint(x: -126.4, y: -72.97)) polygonPath.close() context.saveGState() polygonPath.addClip() context.drawLinearGradient(sVGID_1_2, start: CGPoint(x: -126.4, y: -72.97), end: CGPoint(x: 126.41, y: 72.99), options: [.drawsBeforeStartLocation, .drawsAfterEndLocation]) context.restoreGState() } 

我发布它是因为基本上每一行都在转换为Swift 4时发生了变化,转换它只需要一段时间来检查它是否有效。