为什么 CAShapeLayer 存在?

Why does CAShapeLayer exist?

我正在尝试了解 CAShapeLayer 以及它的闪光点。似乎主要优势是您可以方便地访问的形状样式属性:

let shapeLayer = CAShapeLayer()
shapeLayer.frame = CGRect(origin: CGPoint(x: 100, y: 100), size: .init(width: 200, height: 200))
shapeLayer.fillColor = .none
shapeLayer.lineWidth = 5
shapeLayer.strokeColor = UIColor.blue.cgColor

let path = UIBezierPath()
let withCenter = CGPoint(x: 100, y: 100)
let radius = CGFloat(100)
let startAngle = CGFloat(0.0)
let endAngle = CGFloat(CGFloat.pi * 2)

path.addArc(withCenter: withCenter, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)

shapeLayer.path = path.cgPath

但是,我认为优势到此为止。它反而限制了您将上下文设置为多种状态的能力,例如不同路径的颜色,并且需要新的 CAShapeLayer。我可以覆盖绘图方法或使用委托,但在那种情况下,这与 CALayer 做的事情相同。

另一方面,CALayer:

let layer = CALayer()
layer.frame = CGRect(origin: CGPoint(x: 100, y: 300), size: .init(width: 200, height: 200))
let renderer = UIGraphicsImageRenderer(size: CGSize(width: 200, height: 200))
let image = renderer.image { (_) in
    let path = UIBezierPath()
    let withCenter = CGPoint(x: 100, y: 100)
    let radius = CGFloat(100)
    let startAngle = CGFloat(0.0)
    let endAngle = CGFloat(CGFloat.pi * 2)
    
    path.lineWidth = 5
    UIColor.blue.setStroke()
    path.addArc(withCenter: withCenter, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
    path.stroke()
}

layer.contents = image.cgImage

您可以为不同的路径设置多种描边颜色。显然,您可以以类似的方式设置 CAShapeLayercontents,但我想利用 CAShapeLayer 的 API 的 CALayer不提供。

形状样式属性是CAShapeLayer的主要原因吗?

对我来说,CAShapeLayer 最大的优势是动画。正如 Matt 所说,您可以为 strokeStart and/or strokeEnd 设置动画,使形状看起来像用钢笔绘制的一样,或者消失。您还可以使用 animate strokeStart and/or strokeEnd 来创建各种不同的“擦除”动画。

这是我写的 link 到 post 使用动画到 strokeEnd 以创建“时钟擦除”动画:

How do you achieve a "clock wipe"/ radial wipe effect in iOS?

您还可以为安装到形状图层中的路径设置动画。只要起始路径和结束路径具有相同数量的控制点,系统就会创建一个流畅、优雅的动画。然而,有一些技巧可以使这项工作正常进行。如果您在动画期间更改弧角,弧形动画将无法按预期工作,因为弧形内部由不同数量的三次贝塞尔曲线组成。

查看我在 Github 上的项目 RandomBlobs and TrochoidDemo 以获取动画路径控制点的示例。