ios 如何使用渐变颜色填充贝塞尔曲线路径

jgwigjjp  于 2022-11-26  发布在  iOS
关注(0)|答案(4)|浏览(222)

我的自定义UIView draw(_ rect: CGRect)函数中有一个UIBezierPath。我想用渐变色填充路径。请任何人指导我如何做。
我需要用渐变色填充剪辑,然后用黑色笔划路径。
在SO中有一些帖子并没有解决这个问题。例如Swift: Gradient along a bezier path (using CALayers),这篇帖子指导如何在UIView中的层上绘图,而不是在UIBezierPath中绘图。

注意:我正在处理Swift-3

j2qf4p5b

j2qf4p5b1#

为了回答你的问题
我在自定义UIView绘图中有一个UIBezierPath(_ rect:CGRect)函数。我想用渐变颜色填充路径。
假设有一条椭圆形路径,

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)
hs1ihplo

hs1ihplo2#

您可以直接在Core Graphics中执行此操作,而无需使用CALayer类。使用bezierPath.addClip()将贝塞尔曲线路径设置为剪辑区域。任何后续的绘图命令都将被屏蔽到该区域。
我在我的一个项目中使用了这个 Package 函数:

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: [])
}
webghufk

webghufk3#

这里的其他答案似乎不起作用(至少在较新的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];
nkhmeac6

nkhmeac64#

@AlbertRenshaw(ObjC)答案的Swift 5版本,并 Package 在一个UIView类中。它显示的东西看起来是球形的,但在它的侧面。可以应用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),
    ])
}

相关问题