我在向CAShapeLayer添加渐变时遇到问题。我已经创建了圆形图层,并且想要为其添加渐变。因此,我创建了一个CAGradientLayer并将其框架设置为图层范围,将蒙版设置为图层,但它没有出现。我能做什么?

private func setupCircle() -> CAShapeLayer {
    let circlePath = UIBezierPath(arcCenter: CGPoint(x: progressView.frame.size.width / 2.0, y: progressView.frame.size.height / 2.0), radius: (progressView.frame.size.width - 10)/2, startAngle: 0.0, endAngle: CGFloat(M_PI * 2.0), clockwise: true)

    let circleLayer = CAShapeLayer()
    circleLayer.path = circlePath.CGPath
    circleLayer.fillColor = nil
    circleLayer.strokeColor = UIColor.yellowColor().CGColor
    circleLayer.backgroundColor = UIColor.yellowColor().CGColor
    circleLayer.lineWidth = configurator.lineWidth
    circleLayer.strokeEnd = 1.0

    return circleLayer
}

private func setupGradient() -> CAGradientLayer {
    let gradient = CAGradientLayer()
    gradient.colors = [UIColor.clearColor().CGColor, UIColor.yellowColor().CGColor, UIColor.greenColor().CGColor]
    gradient.locations = [0.0, 0.25, 1.0]
    gradient.startPoint = CGPointMake(0, 0)
    gradient.endPoint = CGPointMake(1, 1)
    return gradient
}

let circle = setupCircle()
let gradient = setupGradient()

gradient.frame = circle.bounds
gradient.mask = circle

progressView.layer.addSublayer(circle)
progressView.layer.insertSublayer(gradient, atIndex: 0)

编辑:
我已经将setupCircle方法更改为:
private func setupCircle() -> CAShapeLayer {
    let circleLayer = CAShapeLayer()
    circleLayer.frame = progressView.bounds.insetBy(dx: 5, dy: 5)
    circleLayer.path = UIBezierPath(ovalInRect: CGRectMake(progressView.center.x, progressView.center.y, progressView.bounds.size.width, progressView.bounds.size.height)).CGPath
    circleLayer.fillColor = nil
    circleLayer.strokeColor = UIColor.yellowColor().CGColor
    circleLayer.backgroundColor = UIColor.yellowColor().CGColor
    circleLayer.lineWidth = configurator.lineWidth
    circleLayer.strokeEnd = 1.0

    return circleLayer
}

在这里,效果是否正确?

ios - CAShapeLayer渐变-LMLPHP

编辑2:
我已经将circleLayer.path = UIBezierPath(ovalInRect: CGRectMake(progressView.center.x, progressView.center.y, progressView.bounds.size.width, progressView.bounds.size.height)).CGPath更改为circleLayer.path = UIBezierPath(ovalInRect: circleLayer.bounds).CGPath,虽然更好,但仍然不是我想要的:

ios - CAShapeLayer渐变-LMLPHP

最佳答案

可以创建图层并将其添加到viewDidLoad中的图层层次结构中,但是您不应该在那里进行任何框架逻辑,因为此时布局不会更新。
尝试将进行任何帧计算的所有代码移到viewDidLayoutSubviews

每次更新布局时也应该这样做,因此将其从setupCircle移到viewDidLayoutSubviews:

let circlePath = UIBezierPath(...)
circleLayer.path = circlePath.cgPath

编辑:

我也看不到你在哪里设置circleLayer的框架?仅仅设置路径是不够的。如果您使用CGRect.zero rect作为遮罩,它将完全隐藏其父图层。

我建议替换为:
let circlePath = UIBezierPath(arcCenter: CGPoint(x: progressView.frame.size.width / 2.0, y: progressView.frame.size.height / 2.0), radius: (progressView.frame.size.width - 10)/2, startAngle: 0.0, endAngle: CGFloat(M_PI * 2.0), clockwise: true)

有了这个:
circleLayer.bounds = progressView.frame.insetBy(dx: 5, dy: 5)
circleLayer.path = UIBezierPath(ovalIn: circleLayer.bounds).cgPath

这样,您将同时设置框架和路径。也要注意坐标系。我不确定progressView在您的视图层次结构中的什么位置,也许您需要使用bounds来代替。

编辑2:
另外,您应该在那里删除几行代码。
  • 这使您的圆形图层完全不透明,使形状本身不可见。

  • circleLayer.backgroundColor = UIColor.yellowColor().CGColor
    
  • 您不应该将圆形添加为子图层,因为您将其用作遮罩:

  • progressView.layer.addSublayer(circle)
    

    09-05 17:26