【问题标题】:Why does CAShapeLayer exist?CAShapeLayer 为什么存在?
【发布时间】:2020-12-03 00:42:16
【问题描述】:

我试图了解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的主要原因吗?

【问题讨论】:

  • 当然,这只是一种方便,就像 CATextLayer 等,对于一个简单的情况,一个带有笔触和填充颜色的贝塞尔路径/CGPath。如果您不想使用它,请不要使用它。如果你这样做,就这样做。
  • 然而,它可以做的一件你会发现很难模仿的事情是当你为它的属性设置动画时,尤其是strokeEnd。实际上,您可能不知道如何使用贝塞尔路径来处理形状层对strokeStartstrokeEnd 的处理。
  • 缩放图像而不是形状图层将无法获得相同的结果
  • IIRC,CAShapeLayer 绘制的形状是矢量图形,而 CALayer,按照您的方式绘制的是位图图像。尝试使用CGAffineTransform 缩放两个图层。
  • @matt 好吧,由于存在关键路径这一事实,我们可以为这些属性设置动画,尽管不是全部。我能够为strokeStartstrokeEndlineWidthmiterLimit 甚至path 本身设置动画。

标签: ios swift core-animation calayer cashapelayer


【解决方案1】:

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

这是我写的一篇文章的链接,它使用动画来 strokeEnd 以创建“时钟擦除”动画:

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

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

查看我在 Github 上的项目 RandomBlobsTrochoidDemo,了解路径控制点的动画示例。

【讨论】:

  • 除了CAShapeLayer的动画能力之外,认为它是使用Core Animation“绘图”的唯一方法是否正确?例如,如果我要使用 CALayer 绘图,它没有像 CAShapeLayer 那样的 path 属性,我将不得不继承并覆盖 draw 或使用 CALayerDelegate,两者它使用核心图形。或者我可以像我的问题一样使用contents 属性,这不是核心动画。
  • 我所说的“使用 Core Animation 绘图”的意思是 CA 使用 GPU 来合成矢量图,而 Core Graphics 使用 CPU。所以我想知道当UIBezierPath 使用CAShapeLayer 时会发生什么。
  • 一般来说,覆盖视图/图层的绘制方法意味着您在 CPU 上使用 CG 调用,而不是 GPU 加速的图形。除了使用形状层之外,我不知道有一种 GPU 加速的方式来渲染路径。在做动画时它变得更加重要。 Core Animation 负责在动画的开始和结束状态之间进行插值,并在其间生成所有帧,并且非常高效地生成这些帧。
猜你喜欢
  • 2021-09-04
  • 2015-11-01
  • 1970-01-01
  • 2021-07-04
  • 1970-01-01
  • 1970-01-01
  • 2021-12-10
  • 2010-11-12
  • 2019-05-12
相关资源
最近更新 更多