CAShapeLayer 1px虚线

时间:2016-04-29 13:38:50

标签: ios swift

我尝试绘制一条像素虚线,但它总是绘制2px线。目前的解决方案:

let shapelayer = CAShapeLayer()
let path = UIBezierPath()
path.moveToPoint(CGPoint(x: x, y: y))
path.addLineToPoint(CGPoint(x: x, y: y))

shapelayer.strokeColor = UIColor.whiteColor().CGColor
shapelayer.lineWidth = 1.0 / UIScreen.mainScreen().scale
shapelayer.lineJoin = kCALineJoinMiter
shapelayer.lineDashPattern = [1, 3]
shapelayer.path = path.CGPath
layer.addSublayer(shapelier)

2 个答案:

答案 0 :(得分:4)

那是因为形状图层不知道你有一个双分辨率的屏幕,所以它绘制了一条点线,它在屏幕上被加倍到2个像素。您需要将形状图层contentsScale设置为屏幕的显示比例。

此问题仅适用于您自己创建的图层(如此图层)。

答案 1 :(得分:2)

@matt is correct关于更改图层的contentsScale - 但这似乎不是您在这里面临的问题。

图层的contentsScale仅影响图层渲染到的“逻辑”像素的后备存储的大小。但是,为了在物理屏幕上显示,将对该后备存储进行向下或向上采样,以匹配实际设备的物理坐标系。

如果在“逻辑”像素的1x内容缩放后备存储中绘制1pt线 - 它将在该坐标系中表示为1px线。但是,必须对其进行上采样才能在2x显示屏上显示。这将有效地将其宽度加倍至2px(尽管上采样的性质意味着您将失去质量)。

如果在2x内容缩放后备存储中绘制1pt行 - 它将在该坐标系中表示为2px行。作为背衬坐标系&物理坐标系匹配,不需要采样,并将在2x显示屏上显示为2px线。

因此contentsScale实际上不会影响物理像素比率的点数。它只影响质量(由于采样)。因此,您应该使用contentsScale的屏幕比例 - 因为您应该将“逻辑”像素的支持显示的比例与设备显示的物理比例相匹配,以避免通过采样造成质量损失。但是,对于线宽使用1.0将在2x显示器上生成2px线,并且无论contentsScale如何,都会在3x显示器上生成3px线,因为线宽仍以点为单位定义。如果您希望以像素为单位测量线宽 - 则需要除以屏幕的比例。

您在问题中看到的问题是,您正在绘制一条线宽为1px的线,但是您为线长度设置了1pt (短划线图案)。因此,这将导致每个片段在2x显示器上占据2x1像素的行。

解决方案是为行短划线模式指定1.0/UIScreen.mainScreen().scale以及为lineWidth指定。例如:

shapelayer.lineDashPattern = [1.0/UIScreen.mainScreen().scale, 3] // set whatever you want for the unstroked line dash length
shapelayer.lineWidth = 1.0/UIScreen.mainScreen().scale

此外,您需要在1x或3x显示屏上将路径偏移0.5点,在2x显示屏上偏移0.25点(或0.75点,具体取决于您要剪切线的像素)。如果它是水平的,你会想要将这个偏移应用于线的y坐标,如果它是垂直的,则需要x坐标。这是因为一条线的笔划将“鞍”线 - 这意味着它将被绘制在它的任何一侧。当您对线的位置使用整数时,您将其绘制在像素边界上。

虽然这在使用点时通常不会产生很大影响 - 但在像素级绘制时这很重要。偏移线将使其与像素的中心对齐 - 这意味着它的笔划仅占据一个像素。如果1px线未与像素中心正确对齐,则会在2像素上显示强度降低 - 从而产生不良影响。

相关问题