首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >UIBezierPath笔划1px线条和填充1px宽度的矩形-不同的结果。

UIBezierPath笔划1px线条和填充1px宽度的矩形-不同的结果。
EN

Stack Overflow用户
提问于 2012-06-24 10:05:45
回答 2查看 21.5K关注 0票数 23

这是一幅简单的图画

代码语言:javascript
运行
AI代码解释
复制
- (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和模拟器上,第一条线模糊,看起来比1px宽,但第二条线清晰。

不幸的是,我既没有iPhone4也没有新的iPad可以测试,但在视网膜模拟器上,这两条线看起来是一样的。

问:矩形而不是笔划是在非视网膜和视网膜设备上获得相同结果的唯一方法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-24 10:22:35

您正在填充矩形的内部,但您正在从中心描边线条。由于这两种情况下的坐标(矩形的角点以及直线中的起点和终点坐标)都定义为整数值(无分数),因此坐标位于精确的点边界上。

我在讨论直线上的点时提到了上面的“坐标”,以免将它们与屏幕上的点混淆。出于同样的原因,我还说了“点边界”而不是“像素边界”。iOS在所谓的“点”而不是像素中定义它的坐标和所有点。点是与分辨率无关的测量。视网膜和非视网膜设备在屏幕上都有相同数量的点,只是它们对应的实际像素数量不同。

让我们来看一下在点边界上画一条线(就像你的问题中那样)与填充一个矩形相比,其中角位于点边界上:

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

在非视网膜的情况下,您可以看到,尝试从中心用1点线(在这种情况下,对应于1像素线宽)绘制线条将填充顶部像素的一半和下方像素的一半。由于像素只填充了一半,因此这些像素的不透明度为50%。这会产生较浅的颜色(白色背景)。因为顶部和下方的像素都是填充的,所以笔划填充了顶部和下方的像素。这使得这条线看起来像是2个像素宽,而不是1个像素。

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

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

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

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

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

票数 53
EN

Stack Overflow用户

发布于 2014-04-24 08:40:20

使用笔划和填充得到不同结果的原因是它们对参数的解释不同。

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

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11176560

复制
相关文章

相似问题

领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文