Path-based 面具很好anti-aliasing

Path-based mask with nice anti-aliasing

我想用圆圈遮盖正方形。我正在使用它而不是角半径,因为我想稍后用动画做一些事情。

我可以把它遮起来,但是边缘很粗糙:

  // Target View
  let targetView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
  targetView.backgroundColor = UIColor.redColor()

  // Mask
  let maskingPath = UIBezierPath()
  let half = targetView.frame.width / 2
  maskingPath.addArcWithCenter(CGPoint(x: half, y: half), radius: half, startAngle: 0, endAngle: 360, clockwise: true)
  let maskingLayer = CAShapeLayer()
  maskingLayer.path = maskingPath.CGPath

  // Maybe setting contentsScale?
  // maskingLayer.contentsScale = UIScreen.mainScreen().scale // doesn't change anything, sorry 
  // Maybe enabling edgeAntialiasing?
  // maskingLayer.allowsEdgeAntialiasing = true // also doesn't change anything
  // Magnification filter?
  // maskingLayer.magnificationFilter = kCAFilterNearest // nuttin'

  targetView.layer.mask = maskingLayer

我已经尝试了 magnificationFilter 和其他一些东西。

如何添加抗锯齿的可动画圆形遮罩?

找到解决方案,但未找到根本原因。

这样会画脆:

let maskingPath = UIBezierPath()
let half = targetView.frame.width / 2
maskingPath.addArcWithCenter(CGPoint(x: half, y: half), radius: half, startAngle: 0, endAngle: 360, clockwise: true)
let maskingLayer = CAShapeLayer()
maskingLayer.path = maskingPath.CGPath
targetView.layer.mask = maskingLayer

这会画得很好并且抗锯齿:

let maskingLayer = CAShapeLayer()
maskingLayer.path = UIBezierPath(ovalInRect: targetView.bounds).CGPath
targetView.layer.mask = maskingLayer

希望我知道为什么。它们都 CGPath 用作图层蒙版。

编辑:Kurt 指出我正在绘制 360 弧度,这就像一遍又一遍地绘制同一个圆圈,看起来不透明并且破坏了正在发生的任何抗锯齿。

您给 addArcWithCenter 一个角度(以度为单位):

maskingPath.addArcWithCenter(CGPoint(x: half, y: half),
                             radius: half,
                             startAngle: 0,
                             endAngle: 360,
                             clockwise: true)

the documentation 声明角度应以弧度为单位。

因此,您正在创建一条自身重叠多次的路径。边缘绘制在边缘先前通过的顶部,在同一位置。在积累足够多的通道后,它们最终看起来不透明(或几乎不透明)。如果您在彼此之上创建多个圆形路径,您会看到类似的东西。

这对我来说效果更好:

maskingPath.addArcWithCenter(CGPoint(x: half, y: half),
                             radius: half,
                             startAngle: 0,
                             endAngle: CGFloat(M_PI * 2.0),
                             clockwise: true)

(但由于您真的想要一个封闭的椭圆,您应该像您在回答中所做的那样使用 UIBezierPath(ovalInRect: targetView.bounds)。)