代码改变世界

一像素宽的竖线

2017-01-15 23:52  v2m  阅读(980)  评论(0编辑  收藏  举报

设计师很多时候会有一像素线的需求,怎么去实现有下面几种方法。

一、 Image

  1. 资源图片
    找设计师要个图片,用UIImageView 或者 CALayer的方式显示出来
  2. CoreGraphics绘制
    用CoreCraphics的方式画一个 UIImage,然后用1的方法展示出来
    此类方法,内存中会多了一个UIImage对象,而且显示时候也多了一层。

二、drawRect:

  1. path stroke方法(详见参考1)
  2. path fill方法
    由于现在的 Retina 屏幕,一般 1 point = 2~3 pixels,在 UIView 的 drawRect: 方法中,系统已经设置好 context 的 scale,所以一像素的线宽 是 1.0 / [UIScreen mainScreen].scale
    根据参考2,当有颜色落在两个 pixel 中间时,由于反锯齿的特性,会在这两个 pixel 上都填充上失真颜色的线。
    扩展下,如果在 1 pixel 中绘制 小于 1pixel 的像素,会充满 1 pixel并且颜色失真;在 2 个pixel 交界的地方绘制小于2 pixel 的线,如果两边比例一致,则2个 pixel 都会以同样失真的颜色绘制,否则比例多的颜色深点,少的浅点;如果跨越很多 pixel 然后边界超出,比如在 8 个 pixel 中绘制 7 pixel,然后两边都有点空余,那么就会在两边填充失真颜色,中间的是正确的颜色。
    Path中 stroke是根据线(line)的位置,向两边各扩散 一半的线宽,所以绘制方法是:使用Path的 moveToPointaddLineToPoint 方法添加一根1 pixel线,然后偏移 目标位置 +0.5 pixel(对应到point 就是 1.0 / [UIScreen mainScreen].scale / 2.0)。
    Path 中 fill 是直接填充框内区域,所以设置好 1 pixel 的区域后,不需要相对目标位置设置偏移。
    对比下下面两段代码,都是画在第一列 pixel 的
	float u = 1.0 / [UIScreen mainScreen].scale;
    
    UIBezierPath* path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(u / 2.0, 0)];
    [path addLineToPoint:CGPointMake(u / 2.0, 50)];
    path.lineWidth = u;
    [[UIColor blackColor] set];
    [path stroke];
	float u = 1.0 / [UIScreen mainScreen].scale;
    
    UIBezierPath* path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, u, 50)];
    [[UIColor blackColor] set];
    [path fill];

三、Layer

这种方法就是建一个1 pixel宽的layer,然后添加到 UIView 的 layer 上,但是也要注意反锯齿的问题,也就是说,如果你把这个 layer 的偏移,设置到了 UIView 的两个 pixel 中间,同样会看到失真的两像素线。

	float u = 1.0 / [UIScreen mainScreen].scale;
    CALayer *layer = [CALayer layer];
    layer.frame = CGRectMake(0, 0, 50, u);
    layer.backgroundColor = [UIColor blackColor].CGColor;
    [self.layer addSublayer:layer];

参考
1.http://www.cnblogs.com/smileEvday/p/iOS_PixelVsPoint.html
2.https://developer.apple.com/library/content/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html#//apple_ref/doc/uid/TP40010156-CH14-SW1