【发布时间】:2026-02-14 09:10:01
【问题描述】:
上图显示了以下代码是如何运行的:
extension Int {
var degreesToRadians: Double { return Double(self) * .pi / 180 }
var radiansToDegrees: Double { return Double(self) * 180 / .pi }
}
extension FloatingPoint {
var degreesToRadians: Self { return self * .pi / 180 }
var radiansToDegrees: Self { return self * 180 / .pi }
}
class SunBurstView: UIView {
override func draw(_ rect: CGRect) {
let radius: CGFloat = rect.size.width / 2
UIColor.yellow.setFill()
let bezierPath = UIBezierPath()
let centerPoint = CGPoint(x: rect.origin.x + radius, y: rect.size.height / 2)
var thisPoint = CGPoint(x: centerPoint.x + radius, y: centerPoint.y + radius)
bezierPath.move(to: centerPoint)
var thisAngle: CGFloat = 0.0
let sliceDegrees: CGFloat = 360.0 / 20 / 2.0
for _ in 0..<20 {
let x = radius * CGFloat(cosf(Float((thisAngle + sliceDegrees).degreesToRadians))) + centerPoint.x
let y = radius * CGFloat(sinf(Float((thisAngle + sliceDegrees).degreesToRadians))) + centerPoint.y
thisPoint = CGPoint(x: x, y: y)
bezierPath.addLine(to: thisPoint)
thisAngle += sliceDegrees
let x2 = radius * CGFloat(cosf(Float((thisAngle + sliceDegrees).degreesToRadians))) + centerPoint.x
let y2 = radius * CGFloat(sinf(Float((thisAngle + sliceDegrees).degreesToRadians))) + centerPoint.y
thisPoint = CGPoint(x: x2, y: y2)
bezierPath.addLine(to: thisPoint)
bezierPath.addLine(to: centerPoint)
thisAngle += sliceDegrees
}
bezierPath.close()
bezierPath.lineWidth = 0
let colors = [UIColor.green.cgColor, UIColor.blue.cgColor] as CFArray
let gradient = CGGradient(colorsSpace: nil, colors: colors, locations: nil)
let endPosition = min(frame.width, frame.height) / 2
let center = CGPoint(x: bounds.size.width / 2, y: bounds.size.height / 2)
UIGraphicsGetCurrentContext()?.drawRadialGradient(gradient!, startCenter: center, startRadius: 0.0, endCenter: center, endRadius: endPosition, options: .drawsAfterEndLocation)
bezierPath.fill()
bezierPath.stroke()
}
}
我希望径向背景只填充 UIBezierPath。通常这可以通过遮罩层来完成,但渐变没有属性遮罩。感谢您对如何仅在 UIBezierPath 上绘制渐变径向背景的任何帮助!在没有 UIBezierPath 的 UIView 上应该是透明的。
带有线性渐变的完整代码(复制粘贴即可):
class SunBurstView: UIView {
override func draw(_ rect: CGRect) {
let radius: CGFloat = rect.size.width / 2
UIColor.yellow.setFill()
let bezierPath = UIBezierPath()
let centerPoint = CGPoint(x: rect.origin.x + radius, y: rect.size.height / 2)
var thisPoint = CGPoint(x: centerPoint.x + radius, y: centerPoint.y + radius)
bezierPath.move(to: centerPoint)
var thisAngle: CGFloat = 0.0
let sliceDegrees: CGFloat = 360.0 / 20 / 2.0
for _ in 0..<20 {
let x = radius * CGFloat(cosf(Float((thisAngle + sliceDegrees).degreesToRadians))) + centerPoint.x
let y = radius * CGFloat(sinf(Float((thisAngle + sliceDegrees).degreesToRadians))) + centerPoint.y
thisPoint = CGPoint(x: x, y: y)
bezierPath.addLine(to: thisPoint)
thisAngle += sliceDegrees
let x2 = radius * CGFloat(cosf(Float((thisAngle + sliceDegrees).degreesToRadians))) + centerPoint.x
let y2 = radius * CGFloat(sinf(Float((thisAngle + sliceDegrees).degreesToRadians))) + centerPoint.y
thisPoint = CGPoint(x: x2, y: y2)
bezierPath.addLine(to: thisPoint)
bezierPath.addLine(to: centerPoint)
thisAngle += sliceDegrees
}
bezierPath.close()
// let colors = [UIColor.green.cgColor, UIColor.blue.cgColor] as CFArray
// let gradient = CGGradient(colorsSpace: nil, colors: colors, locations: nil)
// let endPosition = min(frame.width, frame.height) / 2
// let center = CGPoint(x: bounds.size.width / 2, y: bounds.size.height / 2)
// UIGraphicsGetCurrentContext()?.drawRadialGradient(gradient!, startCenter: center, startRadius: 0.0, endCenter: center, endRadius: endPosition, options: .drawsAfterEndLocation)
//linear
let shape = CAShapeLayer()
shape.path = bezierPath.cgPath
shape.lineWidth = 0.0
shape.strokeColor = UIColor.black.cgColor
self.layer.addSublayer(shape)
let gradient = CAGradientLayer()
gradient.frame = bezierPath.bounds
gradient.colors = [UIColor.blue.cgColor, UIColor.green.cgColor]
let shapeMask = CAShapeLayer()
shapeMask.path = bezierPath.cgPath
gradient.mask = shapeMask
self.layer.addSublayer(gradient)
bezierPath.lineWidth = 0
bezierPath.fill()
bezierPath.stroke()
}
}
【问题讨论】:
-
一种方法:创建一个渐变层,然后使用Path作为图层蒙版。那里有很多示例...只需搜索
UIBezierPath gradient fill,您应该就可以了。 -
@DonMag 是的,我知道遮罩层,我在我的问题中说过。但是渐变没有属性掩码。而在制作新的渐变层时,如何制作圆形渐变呢?
-
你能用线性渐变填充你的 SunBurst 路径吗?
-
@DonMag 是的,带有遮罩层。但是圆形渐变有点难……
-
好的 - 用你用来用线性渐变填充贝塞尔路径的代码更新你的问题......然后我可以告诉你如何将线性渐变更改为径向。