UIBezierPath笔画1px线和填充1px宽的矩形 – 不同的结果。

这是一个简单的绘图

- (void)drawRect:(CGRect)rect { //vertical line with 1 px stroking UIBezierPath *vertLine = [[UIBezierPath alloc] init]; [vertLine moveToPoint:CGPointMake(20.0, 10.0)]; [vertLine addLineToPoint:CGPointMake(20.0, 400.0)]; vertLine.lineWidth = 1.0; [[UIColor blackColor] setStroke]; [vertLine stroke]; //vertical rectangle 1px width UIBezierPath *vertRect= [UIBezierPath bezierPathWithRect:CGRectMake(40.0, 10.0, 1.0, 390.0)]; [[UIColor blackColor] setFill]; [vertRect fill]; } 

在非视网膜3GS和模拟器的第一行是模糊的,看起来比1像素宽,但第二行是脆。

不幸的是我没有iPhone4和新的iPadtesting,但在视网膜模拟器上,两条线看起来都是一样的。

问题:矩形而不是中风是获得非视网膜和视网膜设备相同结果的唯一方法?

您正在填充矩形的内部,但您正在从中心抚摸线条。 由于两种情况下的坐标(矩形的拐angular和线的起始和结束坐标)被定义为整数值(无分数),所以坐标位于精确的点边界上。

谈到线的点时我说过“坐标”,不要将它们与屏幕上的点混淆。 我也说“点边界”,而不是“像素边界”出于同样的原因。 iOS定义了它的坐标和所有点,而不是像素。 一个点是独立于分辨率的测量。 视网膜和非视网膜设备在屏幕上的点数相同,只是它们对应于不同数量的实际像素。

让我们看看抚摸一个位于点边界上的线条(比如在你的问题中),而不是填充一个矩形的angular落在点边界上:

在下面的插图中,我抚摸着一条黑色的线条,在非视网膜屏幕和视网膜屏幕上都填充了一个橙色的长方形。 我也用蓝色概述了这条线和矩形。 在这两种情况下,您都可以看到该分辨率的点的大小,并将其与实际的像素网格进行比较。

在非视网膜的情况下,您可以看到,试图从中心用1点线(在这种情况下对应于1个像素线宽)中间划线将填充像素的上半部分和下半部分下面。 由于像素只有一半被填充,所以这些像素的不透明度是50%。 这导致颜色较浅(在白色背景上)。 由于顶部和底部的像素都是派对填充的,所以抚摸顶部和底部的像素。 这使得该线看起来好像是2个像素宽而不是1个。

您可以快速将其与内部填充的矩形进行比较。

非视网膜

视网膜屏幕上的相同情况看起来不同。 在这种情况下,点的大小是相同的,但是它由4个像素组成,而不是1个。这一次,当抚摸线时,线上方半点和线下方半点将完全填充像素行由于屏幕分辨率更高,所以上下都是这样。 这意味着该线看起来好像是1点宽,而且颜色看起来完全不透明。

我们也可以看到填充的矩形看起来是一样的。

视网膜


要解决这个问题,你可以把你的线的点放在半个像素上。 在低分辨率设备上从中心划线,意味着该线向上延伸半个点,向下延伸半个点。 由于线的中心现在位于点的中心,这意味着描边线完全位于像素内并且线看上去很锐利。 这样做不会对视网膜线有任何影响,因为向下(或向上)移动半个点,仍然意味着您完全填充了上下的像素。

在下面的例子(对于视网膜),我已经显示了点网格和像素网格。

半像素非视网膜半像素视网膜

中风和填充得到不同结果的原因是他们对争辩的解释是不同的。

笔画在坐标的每一侧添加线的一半宽度。 所以,你的观点是20.0,线宽是1px。 结果将是理论上(19.5-20.5)之间的1像素黑线。 由于设备屏幕上没有任何非整数像素,因此将在(19-21)之间转换为2像素灰色/模糊线。 为了避免这种情况,需要将每个坐标与0.5(如CGPointMake(20.5,10.5))相同,这样宽度将不再在像素之间分配。

但是,填充中的参数用于设置要填充的区域的边框,CGRectMake(40.0,10.0,1.0,390.0)意味着(40-41)之间的区域。 因此像素上没有小数部分看起来模糊。