[英]How to fill a bezier path with gradient color
我的自定義UIView draw(_ rect: CGRect)
function 中有一個UIBezierPath
。我想用漸變顏色填充路徑。 請任何人都可以指導我該怎么做。
我需要用漸變顏色填充剪輯,然后用黑色描邊路徑。
SO中有一些帖子沒有解決問題。 例如Swift:沿貝塞爾曲線路徑漸變(使用 CALayers)這篇文章指導如何在UIView
而非UIBezierPath
中的圖層上繪制。
注意:我正在研究 Swift-3
要回答你的這個問題,
我的自定義 UIView draw(_ rect: CGRect) 函數中有一個 UIBezierPath。 我想用漸變色填充路徑。
假設您有一條橢圓形路徑,
let path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 100, height: 100))
要創建漸變,
let gradient = CAGradientLayer()
gradient.frame = path.bounds
gradient.colors = [UIColor.magenta.cgColor, UIColor.cyan.cgColor]
我們需要一個漸變的遮罩層,
let shapeMask = CAShapeLayer()
shapeMask.path = path.cgPath
現在將此shapeLayer
設置為gradient
圖層的mask
,並將其添加到view
的圖層作為subLayer
gradient.mask = shapeMask
yourCustomView.layer.addSublayer(gradient)
更新創建一個帶有描邊的基礎層,並在創建漸變層之前添加。
let shape = CAShapeLayer()
shape.path = path.cgPath
shape.lineWidth = 2.0
shape.strokeColor = UIColor.black.cgColor
self.view.layer.addSublayer(shape)
let gradient = CAGradientLayer()
gradient.frame = path.bounds
gradient.colors = [UIColor.magenta.cgColor, UIColor.cyan.cgColor]
let shapeMask = CAShapeLayer()
shapeMask.path = path.cgPath
gradient.mask = shapeMask
self.view.layer.addSublayer(gradient)
您可以直接在 Core Graphics 中執行此操作,而無需使用CALayer
類。 使用bezierPath.addClip()
將貝塞爾路徑設置為剪切區域。 任何后續繪圖命令都將被屏蔽到該區域。
我在我的一個項目中使用了這個包裝函數:
func drawLinearGradient(inside path:UIBezierPath, start:CGPoint, end:CGPoint, colors:[UIColor])
{
guard let ctx = UIGraphicsGetCurrentContext() else { return }
ctx.saveGState()
defer { ctx.restoreGState() } // clean up graphics state changes when the method returns
path.addClip() // use the path as the clipping region
let cgColors = colors.map({ $0.cgColor })
guard let gradient = CGGradient(colorsSpace: nil, colors: cgColors as CFArray, locations: nil)
else { return }
ctx.drawLinearGradient(gradient, start: start, end: end, options: [])
}
這里的其他答案似乎不起作用(至少在較新的 iOS 版本中?)
這是一個正在創建貝塞爾路徑並且描邊是漸變描邊的工作示例,根據需要調整 CGPoints 和 CGColors:
CGPoint start = CGPointMake(300, 400);
CGPoint end = CGPointMake(350, 400);
CGPoint control = CGPointMake(300, 365);
UIBezierPath *path = [UIBezierPath new];
[path moveToPoint:start];
[path addQuadCurveToPoint:end controlPoint:control];
CAShapeLayer *shapeLayer = [CAShapeLayer new];
shapeLayer.path = path.CGPath;
shapeLayer.strokeColor = [UIColor whiteColor].CGColor;
shapeLayer.fillColor = [UIColor clearColor].CGColor;
shapeLayer.lineWidth = 2.0;
//[self.view.layer addSublayer:shapeLayer];
CGRect gradientBounds = CGRectMake(path.bounds.origin.x-shapeLayer.lineWidth, path.bounds.origin.y-shapeLayer.lineWidth, path.bounds.size.width+shapeLayer.lineWidth*2.0, path.bounds.size.height+shapeLayer.lineWidth*2.0);
CAGradientLayer *gradientLayer = [CAGradientLayer new];
gradientLayer.frame = gradientBounds;
gradientLayer.bounds = gradientBounds;
gradientLayer.colors = @[(id)[UIColor redColor].CGColor, (id)[UIColor blueColor].CGColor];
gradientLayer.mask = shapeLayer;
[self.view.layer addSublayer:gradientLayer];
Swift @AlbertRenshaw (ObjC) 答案的 5 個版本,並包裹在 UIView class 中。它顯示的內容看起來是球形的,但在它的側面。 可以應用 CGAffineTransform 將其旋轉 90º 以獲得炫酷效果。
進口 UIKit
class SphereView : UIView {
override func draw(_ rect: CGRect) {
super.draw(rect)
let centerPoint = CGPoint(x: frame.width / 2, y: frame.height / 2)
let radius = frame.height / 2
let circlePath = UIBezierPath(arcCenter: centerPoint,
radius: radius,
startAngle: 0,
endAngle: .pi * 2,
clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.cgPath;
shapeLayer.strokeColor = UIColor.green.cgColor
shapeLayer.lineWidth = 2.0;
let gradientBounds = CGRectMake(
circlePath.bounds.origin.x - shapeLayer.lineWidth,
circlePath.bounds.origin.y - shapeLayer.lineWidth,
circlePath.bounds.size.width + shapeLayer.lineWidth * 2.0,
circlePath.bounds.size.height + shapeLayer.lineWidth * 2.0)
let gradientLayer = CAGradientLayer()
gradientLayer.frame = gradientBounds;
gradientLayer.bounds = gradientBounds;
gradientLayer.colors = [UIColor.red, UIColor.blue].map { $0.cgColor }
gradientLayer.mask = shapeLayer;
self.layer.addSublayer(gradientLayer)
}
}
在 UIViewController 中的用法:
override func viewDidLoad() {
view.backgroundColor = .white
let sphereView = SphereView()
sphereView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(sphereView)
NSLayoutConstraint.activate([
sphereView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
sphereView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
sphereView.widthAnchor.constraint(equalToConstant: 150),
sphereView.heightAnchor.constraint(equalToConstant: 150),
])
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.