设置CAShapeLayer lineWidth小于1

时间:2016-04-05 10:21:08

标签: ios objective-c uibezierpath cashapelayer

在上面的屏幕截图中,有两行:

  1. 实线只是UIView,高度为1px
  2. 使用此代码
  3. 创建虚线
    - (void)viewDidAppear:(BOOL)animated {
        CAShapeLayer *line = [CAShapeLayer layer];
        UIBezierPath *linePath=[UIBezierPath bezierPath];
    
        [linePath moveToPoint:CGPointMake(0, 107)];
        [linePath addLineToPoint:CGPointMake(self.view.frame.size.width, 107)];
    
        line.lineWidth = 0.5;
        line.path=linePath.CGPath;
        line.fillColor = [[UIColor blackColor] CGColor];
        line.strokeColor = [[UIColor blackColor] CGColor];
    
        [line setLineJoin:kCALineJoinRound];
        [line setLineDashPattern: [NSArray arrayWithObjects:[NSNumber numberWithInt:10], [NSNumber numberWithInt:5],nil]];
    
        [[self.view layer] addSublayer:line];
    }
    

    为什么{1}的1像素(UIView)高度小于1.0高度的虚线?

    我希望虚线像实线一样细长。

2 个答案:

答案 0 :(得分:3)

当你说UIView的身高是1px时,你实际上意味着1px吗?

UIKit中的尺寸(分别为lineWidthframe的{​​{1}}和CAShapeLayer)以points, not pixels衡量。单点相当于1x显示器上的1个像素,2x显示器上的2个像素和3x显示器上的3个像素。*

因此,如果你想要点的单个像素的大小 - 你想要

UIView

您在图片中遇到的问题是,您将1.0/[UIScreen mainScreen].scale 的框架原点与UIView的行混淆。这些都不一样。框架原点代表UIBezierPath顶部 - 而该行代表路径的中心

因此,您需要将线条位置向下偏移其宽度的一半 - 这会将其与像素的中心对齐,从而允许在单个像素上渲染笔划。**

这样的事情应该能达到你想要的效果:

UIView

生成以下内容(在iPhone 6上):

enter image description here

* iPhone 6 Plus的表现略有不同 - 它的物理显示比例(~2.6x)与逻辑音阶(3x)不匹配。

因此,您在其中执行的任何绘图can result in pixel bleeding,因为它会缩小显示。 可以解决这个问题,但involves delving into Open GL or Metal可以进行绘图。

See also here可以很好地概述每部iPhone如何呈现其内容。

**在2倍显示屏上,您 像素边界),as Andrea says

答案 1 :(得分:1)

0.5分将转换为:

  • 1.5xx @ 3x视网膜显示器
  • 1xx on @ 2x retina display
  • 正常显示
  • 0.5

0.5不是像素坐标系中的物理尺度(半像素不存在),因此渲染系统通常会在呈现小数的所有内容周围创建抗锯齿。

这种情况也会导致UIView可能你已经看到它们周围出现了不必要的模糊,当帧有小数点时会发生这种情况,通常可以通过在帧中传递帧来修复CGRectIntegral功能。
要绘制一条像素线,我引用Apple indications about it

  

在高分辨率显示器(比例因子为2.0)上,有一条线   是一点广泛不是抗锯齿,因为它占两个   全像素(从-0.5到+0.5)。画一条只覆盖一条线的线   单个物理像素,你需要使它成为0.5点   厚度并将其位置偏移0.25点