一像素宽的竖线
2017-01-15 23:52 v2m 阅读(980) 评论(0) 编辑 收藏 举报设计师很多时候会有一像素线的需求,怎么去实现有下面几种方法。
一、 Image
- 资源图片
找设计师要个图片,用UIImageView 或者 CALayer的方式显示出来 - CoreGraphics绘制
用CoreCraphics的方式画一个 UIImage,然后用1的方法展示出来
此类方法,内存中会多了一个UIImage对象,而且显示时候也多了一层。
二、drawRect:
- path stroke方法(详见参考1)
- 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的 moveToPoint 和 addLineToPoint 方法添加一根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