簡體   English   中英

如何用漸變顏色填充貝塞爾曲線路徑

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM