我正在尝试像这样使用 Swift 在 UIView 上画一条线:
CGContextSetLineWidth(context, 1.0)
CGContextBeginPath(context)
CGContextMoveToPoint(context, x1, y1)
CGContextAddLineToPoint(context, x2, y2)
CGContextStrokePath(context)
但是绘制的线是 2 像素宽。我尝试了另一种方式:
CGContextSetLineWidth(context, 0.5)
CGContextBeginPath(context)
CGContextMoveToPoint(context, x1, y1)
CGContextAddLineToPoint(context, x2, y2)
CGContextStrokePath(context)
但结果是一样的。 我做错了什么以及如何使用 Swift 在 UIView 上绘制一条 1 像素宽的线?
最佳答案
这里有两个问题:
CoreGraphics 绘图函数以点(屏幕布局的单位,在所有设备上的近似物理尺寸是恒定的)而不是以像素为单位工作。每个点的像素数在屏幕比例不同的设备上是不同的:iPad 2 和 iPad mini 是 iOS 7 及更高版本中唯一支持的 1x 设备,iPhone 4、iPad 3、iPad mini 2 及更高版本为 2x,iPhone 6 除外/6s/7 Plus 是 3x。因此,如果您想要单设备像素的细线,则在大多数当前设备上需要 0.5 磅的线宽(在 iPhone 6 Plus 上需要 0.33 磅的线宽)。
一条线的宽度以一个点的正方形区域为中心。因此,如果您有一条从 (10.0, 10.0) 到 (10.0, 20.0) 的线,它实际上位于 x 坐标为 10.0 和 9.0 的像素之间 — 渲染时,抗锯齿将遮蔽 10.0 和 9.0 列的像素在 50% 的线条颜色下,而不是在 100% 处对一列进行着色。要解决此问题,您需要定位您的线条,使其完全位于一个像素内。 (设备像素,而不是布局点。)
因此,要获得一个像素的细线,您需要减小线宽并根据屏幕的比例因子改变所绘制的点的偏移量。这是执行此操作的测试用例的扩展:
// pass in the scale of your UIScreen
func drawHairline(in context: CGContext, scale: CGFloat, color: CGColor) {
// pick which row/column of pixels to treat as the "center" of a point
// through which to draw lines -- favor true center for odd scales, or
// offset to the side for even scales so we fall on pixel boundaries
let center: CGFloat
if Int(scale) % 2 == 0 {
center = 1 / (scale * 2)
} else {
center = 0
}
let offset = 0.5 - center // use the "center" choice to create an offset
let p1 = CGPoint(x: 50 + offset, y: 50 + offset)
let p2 = CGPoint(x: 50 + offset, y: 75 + offset)
// draw line of minimal stroke width
let width = 1 / scale
context.setLineWidth(width)
context.setStrokeColor(color)
context.beginPath()
context.move(to: p1)
context.addLine(to: p2)
context.strokePath()
}
centerChoice
计算概括了必须选择在哪个子点像素上绘制线条的问题。您必须通过点的中心(偏移 0.5)绘制以在 1x 显示器上遮蔽整个像素或在 3x 显示器上仅遮蔽该点的中间像素,但在 2x 显示器上偏移 0.5 位于两个像素之间这构成了一个点。因此,对于 2x,您必须选择偏移量 0.25 或偏移量 0.75 — center
行通常对偶数或奇数比例因子执行此操作。
注意#1:我将您的测试用例更改为绘制一条垂直线,因为这样更容易看到抗锯齿的效果。无论如何,对角线都会得到一些抗锯齿,但如果宽度和位置正确,垂直线或水平线将不会得到抗锯齿。
注意 #2:iPhone 6/6s/7 Plus 的逻辑比例为 3.0,物理显示比例约为 2.61 — 您可能想尝试使用 screen.scale
与 screen.nativeScale
看看哪个能让你得到更好看的结果。
关于ios - Swift - UIView 绘制 1 像素宽的线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27385929/