CAShapeLayer 和 UIBezierPath 逆时针绘制圆的问题

An issue with CAShapeLayer and UIBezierPath drawing circle counterclockwise

我想画一个圆圈,起点和终点都在逆时针方向的 12 点。我遇到的问题是没有绘制形状。 我正在为路径使用 init(arcCenter center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat, clockwise: Bool) 初始值设定项,如果我使用 clockwise: true,它会起作用。如果 startAngle 设置为 0 并且 endAngle 设置为 2 * .pi,则它与 clockwise: false 一起使用。但是 clockwise: falsestartAngle: -0.5 * .pi, endAngle: 1.5 * .pi 的组合不起作用。这有什么原因吗?我该如何解决?

这个有效:

let shapeLayer = CAShapeLayer()
let arcCenter = view.center
let circularPath = UIBezierPath(arcCenter: arcCenter, radius: 100, startAngle: 0, endAngle: 2 * CGFloat.pi, clockwise: false)
shapeLayer.path = circularPath.cgPath
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.lineWidth = 10
shapeLayer.lineCap = .round
shapeLayer.fillColor = .none
view.layer.addSublayer(shapeLayer)

还有这个。结果看起来一样。

UIBezierPath(arcCenter: arcCenter, radius: 100, startAngle: -0.5 * .pi, endAngle: 1.5 * .pi, clockwise: true)

但不是这个:

UIBezierPath(arcCenter: arcCenter, radius: 100, startAngle: -0.5 * .pi, endAngle: 1.5 * .pi, clockwise: false)

用度数来考虑这个更容易。

  • -0.5 * .pi 弧度等于 -90
  • 1.5 * .pi 弧度等于 270
  • 0度在圆middle-right处

不过仔细想想,-90270在圆上的位置是一样的。


clockwise = true:

UIBezierPath(arcCenter: arcCenter, radius: 100, startAngle: -0.5 * .pi, endAngle: 1.5 * .pi, clockwise: true)

clockwise = false:

UIBezierPath(arcCenter: arcCenter, radius: 100, startAngle: -0.5 * .pi, endAngle: 1.5 * .pi, clockwise: false)

那么为什么 clockwise 画的很远,而逆时针不画呢?看看这个:

如果你在圆上选择两个点(或者你可以说是角度)并逐渐增加其中一个,你可以看到环 lengthens/shortens 根据它是否会 clockwise/counterclockwise。这些圆环相互补充——如果您将 clockwise 圆环放在 counterclockwise 圆环之上,它们将完美地组合成一个圆圈。

因此,当您增加终点使其等于起点 (start: -90, end: 270) 时:

  • clockwise 戒指会满
  • counterclockwise 环将是空的

而当你切换底片时 (start: 90, end: -270):

  • clockwise 环将是空的
  • counterclockwise 戒指会满

另外,这里有一个方便的 (感谢@Leo Dabus!)所以你不必再处理弧度了:

extension BinaryInteger {
    var degreesToRadians: CGFloat { CGFloat(self) * .pi / 180 }
}

extension FloatingPoint {
    var degreesToRadians: Self { self * .pi / 180 }
    var radiansToDegrees: Self { self * 180 / .pi }
}

/// usage:
UIBezierPath(arcCenter: arcCenter, radius: 100, startAngle: -90.degreesToRadians, endAngle: 270.degreesToRadians, clockwise: true)