2013-05-02 55 views
12

我想用2種不同顏色的1px線條繪製雙色線條。 我有很多代碼,所以我在試圖解釋之後加以說明。CALayer drawInContext無法在視網膜顯示器上繪製1px線條

如果我使用的UIView drawRect方法能正常工作時,我關掉抗鋸齒但是當我使用層的drawLayerInContext它要麼顯示一個簡單的線,或與抗鋸齒關閉2px的與antialising或兩個半透明線2px的2條平原線線上。

我設法通過創建一個自定義背景圖像,以獲得比的UIView的drawRect方法類似的行爲,我可以指定一個規模:

UIGraphicsBeginImageContextWithOptions([self bounds].size, NO, 0.f); // 0.f for scale means "scale for device's main screen". 

我只是想知道爲什麼我沒有得到在drawInContext中有相同的行爲,是否有辦法獲得類似的行爲。

這裏是繪製雙色行代碼:

void DRAW_DOUBLE_LINE(CGContextRef ctx, CGPoint startPoint, CGPoint endPoint, UIColor* topColor, UIColor* bottomColor) 
{ 
    UIGraphicsPushContext(ctx); 

    UIBezierPath *topLine = [[UIBezierPath alloc] init]; 
    CGPoint topLineStartPoint = startPoint; 
    CGPoint topLineEndPoint = endPoint; 
    [topLine moveToPoint:topLineStartPoint]; 
    [topLine addLineToPoint:topLineEndPoint]; 
    [topColor setStroke]; 
    topLine.lineWidth = 0.5; 
    [topLine stroke]; 

    UIBezierPath *bottomLine = [[UIBezierPath alloc] init]; 
    CGPoint bottomLineStartPoint = topLineStartPoint; 
    bottomLineStartPoint.y +=0.5; 
    CGPoint bottomLineEndPoint = topLineEndPoint; 
    bottomLineEndPoint.y +=0.5; 
    [bottomLine moveToPoint:bottomLineStartPoint]; 
    [bottomLine addLineToPoint:bottomLineEndPoint]; 
    [bottomColor setStroke]; 
    bottomLine.lineWidth = 0.5; 
    [bottomLine stroke]; 

    UIGraphicsPopContext(); 
} 

隨着UIViewdrawRect方法我得到這樣的:

 
| Points y coordinate | Antialiasing | Result       | 
| ------------------- | ------------ | ------------------------------- | 
| 5     | NO   | 2 lines of 1 px: Bingo!   | 
| 5.25    | NO   | 2 lines of 1 px: Bingo!   | 
| 5.5     | NO   | 2 lines of 1 px: Bingo!   | 
| 5     | YES   | 3 half transparent lines of 1px | 
| 5.25    | YES   | 2 lines of 1 px: Bingo!   | 
| 5.5     | YES   | 3 half transparent lines of 1px | 

與drawInContext一個CALayer的我得到這些結果

 
| Points y coordinate | Antialiasing | Result       | 
| ------------------- | ------------ | ------------------------------- | 
| 5     | NO   | 2 lines of 2 px     | 
| 5.25    | NO   | 1 line of 2 px     | 
| 5.5     | NO   | 1 line of 2 px     | 
| 5     | YES   | 2 half transparent lines of 2px | 
| 5.25    | YES   | 1 half transparent line of 2px | 
| 5.5     | YES   | 2 half transparent lines of 2px | 

使用我的自定義上下文我得到這個:

 
| Points y coordinate | Antialiasing | Result       | 
| ------------------- | ------------ | ------------------------------- | 
| 5     | NO   | 2 lines of 1 px: Bingo!  | 
| 5.25    | NO   | 2 lines of 1 px: Bingo!  | 
| 5.5     | NO   | 2 lines of 1 px: Bingo!  | 
| 5     | YES   | 3 half transparent lines of 1px | 
| 5.25    | YES   | 2 lines of 1 px: Bingo!  | 
| 5.5     | YES   | 3 half transparent lines of 1px | 

代碼drawRect實現:

- (void)drawRect:(CGRect)rect 
{ 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    CGPoint startPoint = CGPointMake(0, 5); 
    CGPoint endPoint = CGPointMake(CGRectGetMaxX(self.bounds),5); 

    UIColor* topLineColor = [UIColor whiteColor]; 
    UIColor* bottomLineColor = [UIColor blackColor]; 

    DRAW_DOUBLE_LINE(context, startPoint, endPoint, topLineColor, bottomLineColor); 
} 

代碼drawInContext實現:

-(void)drawInContext:(CGContextRef)ctx{ 
    CGPoint startPoint = CGPointMake(0, 5); 
    CGPoint endPoint = CGPointMake(CGRectGetMaxX(self.bounds),5); 

    UIColor* topLineColor = [UIColor whiteColor]; 
    UIColor* bottomLineColor = [UIColor blackColor]; 

    DRAW_DOUBLE_LINE(ctx, startPoint, endPoint, topLineColor, bottomLineColor); 
} 

代碼中的CALayer的display方法定義上下文實現:

-(void)display{ 

    if ([UIScreen instancesRespondToSelector:@selector(scale)]) { 
     UIGraphicsBeginImageContextWithOptions([self bounds].size, NO, 0.f); // 0.f for scale means "scale for device's main screen". 
    } else { 
     UIGraphicsBeginImageContext([self bounds].size); 
    } 

    CGContextRef context = UIGraphicsGetCurrentContext(); 

    CGPoint startPoint = CGPointMake(0, 5.25); 
    CGPoint endPoint = CGPointMake(CGRectGetMaxX(self.bounds),5.25); 
    UIColor* topLineColor = [UIColor whiteColor]; 
    UIColor* bottomLineColor = [UIColor blackColor]; 

    DRAW_DOUBLE_LINE(ctx, startPoint, endPoint, topLineColor, bottomLineColor); 

    UIImage *coloredImg = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    self.contents = (id)coloredImg.CGImage; 
} 
+0

你有沒有試圖改變'contentsScale'? – cahn 2014-03-07 00:57:58

回答

0

我會建議,而不是繪製線條,只需繪製所需大小的填充矩形。具有不同分辨率的棘手部分之一是線的起點和終點的位置。但繪製矩形更容易。

矩形的座標始終均勻,因爲您的目標是邊緣而不是像素的中心。

0

繪製並填充矩形而不是線條。矩形的座標應始終位於像素的邊緣而不是中心。

1

不要使用0.5作爲寬度。

1.0/[UIScreen mainScreen].scale

取代0.5當你畫上一層就可以得到1個像素寬度線。

0

我發現在視網膜/非視網膜上看到精確/清晰的1px線條並將它們保持爲1px的最佳方式即使放大也是寫入着色器。在我的情況下,我使用的是OpenGL,但我相信你可以使用Metal for CALayers來做到這一點。基本的過程是繪製一個零高度的矩形(或者如果您的線是垂直的,則爲零寬度),然後在着色器中將這些點向外按所需的像素數。

我從這裏的想法:https://www.mapbox.com/blog/drawing-antialiased-lines/

相關問題