設計師很多時候會有一像素線的需求,怎麼去實現有下麵幾種方法。 一、 Image 1. 資源圖片 找設計師要個圖片,用UIImageView 或者 CALayer的方式顯示出來 2. CoreGraphics繪製 用CoreCraphics的方式畫一個 UIImage,然後用1的方法展示出來 此類方法 ...
設計師很多時候會有一像素線的需求,怎麼去實現有下麵幾種方法。
一、 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