CAShapeLayer 左上角缺少像素

CAShapeLayer missing pixel in top-left corner

我正在使用 CAShapeLayerUIBezierPath 在视图中绘制带边框的框。

这工作正常,但第一个像素(顶部,左侧)未绘制。

这是我的代码:

let focusSize = CGRect(x: focusX, y: focusY, width: focusWidth, height: focusHeight)
let focusPath = UIBezierPath(roundedRect: focusSize, cornerRadius: 0)

let borderLayer = CAShapeLayer()
borderLayer.path = focusPath.cgPath
borderLayer.fillColor = UIColor.clear.cgColor
borderLayer.strokeColor = UIColor.white.cgColor
borderLayer.lineWidth = 2
borderLayer.frame = self.someView.bounds
self.someView.layer.addSublayer(borderLayer)

结果(注意左上角的像素):

我认为这可能与抗锯齿有关,但调整 x、y 和 borderWidth 似乎无法解决问题。 有谁知道是什么原因造成的?

出于某种原因,当您使用 (roundedRect rect: CGRect, cornerRadius: CGFloat) 创建路径时,它没有关闭(尽管它在文档中有说明)。

调用 focusPath.close() 关闭路径并删除丢失的像素。

但是,如果您不想要圆角,只需使用普通矩形即可正确绘制。

let focusPath = UIBezierPath(rect: focusSize)

任何对这里感兴趣的人都是结果路径:

UIBezierPath(roundedRect:  CGRect(x: 10, y: 10, width: 100, height: 100), cornerRadius: 0)
<UIBezierPath: 0x6180000b8000; <MoveTo {10, 10}>,
 <LineTo {110, 10}>,
 <LineTo {110, 110}>,
 <LineTo {10, 110}>,
 <LineTo {10, 10}>,
 <LineTo {10, 10}>

//After calling path.close()
<UIBezierPath: 0x6180000b8000; <MoveTo {10, 10}>,
 <LineTo {110, 10}>,
 <LineTo {110, 110}>,
 <LineTo {10, 110}>,
 <LineTo {10, 10}>,
 <LineTo {10, 10}>,
 <Close>

 UIBezierPath(rect: CGRect(x: 10, y: 10, width: 100, height: 100))
<UIBezierPath: 0x6180000b7f40; <MoveTo {10, 10}>,
 <LineTo {110, 10}>,
 <LineTo {110, 110}>,
 <LineTo {10, 110}>,
 <Close>

设置 lineCap 可能会使框正确显示,但无法解决问题,因为它只是扩展了可见端点并掩盖了缺失的位。设置 borderLayer.lineJoin = kCALineJoinBevel 看看为什么这会成为问题。

您看到矩形上缺少像素的原因是您没有正确配置 lineCap 属性。

尝试添加这一行:

borderLayer.lineCap = kCALineCapSquare

有关行上限(和理解也很重要的行连接)的更多信息,请参阅此页面:http://calayer.com/core-animation/2016/05/22/cashapelayer-in-depth.html#line-cap

是的,根据文档,它应该是一个矩形,但我认为它没有提到 lineWidth

这似乎是您看到缺少像素的原因

borderLayer.lineWidth = 2

现在,当您将宽度更改为 1 时,它会绘制一个完美的矩形,不会丢失任何像素

将 lineWidth 更改为 10 显示间隙有相当大的差异

你的问题的解决方案就是使用这个

borderLayer.lineCap = kCALineCapSquare

勾选这些lineCap & Line Cap Values