[ios]ios畫線 使用CGContextRef,CGPath和UIBezierPath來繪畫


參考 :http://www.mgenware.com/blog/?p=493

 

這三種東西:CGContextRefCGPathUIBezierPath。本質上都是一樣的,都是使用Quartz來繪畫。只不過把繪圖操作暴露在不同的API層面上,在具體實現上,當然也會有一些細小的差別。

我們將主要使用這3個類型,繪制出同一張圖片,如下,一個笑臉:

首先使用Quartz的CGPath來做這張圖。很簡單,首先創建用於轉移坐標的Transform,然后創建一個CGMutablePathRef(屬於CGPath類型)對象。接着通過兩個CGPathAddEllipseInRect和一個CGPathAddArc函數來繪制Path中的兩個眼睛和一個嘴,注意把CGAffineTransform的地址傳進去,這樣Transform才會應用。接着把這個創建好的CGPath加入到當前CGContextRef中,最后通過CGContextRef執行繪畫。

代碼:

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    //開始圖像繪圖
    UIGraphicsBeginImageContext(self.view.bounds.size);
    //獲取當前CGContextRef
    CGContextRef gc = UIGraphicsGetCurrentContext();
    
    //創建用於轉移坐標的Transform,這樣我們不用按照實際顯示做坐標計算
    CGAffineTransform transform = CGAffineTransformMakeTranslation(50, 50);
    //創建CGMutablePathRef
    CGMutablePathRef path = CGPathCreateMutable();
    //左眼
    CGPathAddEllipseInRect(path, &transform, CGRectMake(0, 0, 20, 20));
    //右眼
    CGPathAddEllipseInRect(path, &transform, CGRectMake(80, 0, 20, 20));
    //
    CGPathMoveToPoint(path, &transform, 100, 50);
    CGPathAddArc(path, &transform, 50, 50, 50, 0, M_PI, NO);
    //將CGMutablePathRef添加到當前Context內
    CGContextAddPath(gc, path);
    //設置繪圖屬性
    [[UIColor blueColor] setStroke];
    CGContextSetLineWidth(gc, 2);
    //執行繪畫
    CGContextStrokePath(gc);
    
    //從Context中獲取圖像,並顯示在界面上
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    UIImageView *imgView = [[UIImageView alloc] initWithImage:img];
    [self.view addSubview:imgView];
}

接下來,我們不去使用CGPath類型的相關函數,而完全使用CGContextRef相關的函數,這些函數執行起來其實是和上面講的的CGPath完全等價的。

這里需要注意的是,完全使用CGContextRef的話,Transform的應用需使用CGContextTranslateCTM函數。

完整代碼:

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    //開始圖像繪圖
    UIGraphicsBeginImageContext(self.view.bounds.size);
    //獲取當前CGContextRef
    CGContextRef gc = UIGraphicsGetCurrentContext();
    
    //使用CGContextTranslateCTM函數來轉移坐標的Transform,這樣我們不用按照實際顯示做坐標計算
    CGContextTranslateCTM(gc, 50, 50);
    //左眼
    CGContextAddEllipseInRect(gc, CGRectMake(0, 0, 20, 20));
    //右眼
    CGContextAddEllipseInRect(gc, CGRectMake(80, 0, 20, 20));
    //
    CGContextMoveToPoint(gc, 100, 50);
    CGContextAddArc(gc, 50, 50, 50, 0, M_PI, NO);
    //設置繪圖屬性
    [[UIColor blueColor] setStroke];
    CGContextSetLineWidth(gc, 2);
    //執行繪畫
    CGContextStrokePath(gc);
    
    //從Context中獲取圖像,並顯示在界面上
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    UIImageView *imgView = [[UIImageView alloc] initWithImage:img];
    [self.view addSubview:imgView];
}

同樣會繪制出上面的圖形。

 

最后我們使用UIBezierPath類型來完成上述圖形,UIBezierPath很有意思,它包裝了Quartz的相關API,自己存在於UIKit中,因此不是基於C的API,而是基於Objective-C對象的。那么一個非常重要的點是由於離開了Quartz繪圖,所以不需要考慮Y軸翻轉的問題,在畫弧的時候,clockwise參數是和現實一樣的,如果需要順時針就傳YES,而不是像Quartz環境下傳NO的。

其次橢圓的創建需使用bezierPathWithOvalInRect方法,這里名字是Oral而不是Quartz中的Ellipse

最后注意UIBezierPathapplyTransform方法需要最后調用。

完整代碼:

 

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    //開始圖像繪圖
    UIGraphicsBeginImageContext(self.view.bounds.size);
    
    //創建UIBezierPath
    UIBezierPath *path = [UIBezierPath bezierPath];
    //左眼
    [path appendPath:[UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 20, 20)]];
    //右眼
    [path appendPath:[UIBezierPath bezierPathWithOvalInRect:CGRectMake(80, 0, 20, 20)]];
    //
    [path moveToPoint:CGPointMake(100, 50)];
    //注意這里clockwise參數是YES而不是NO,因為這里不知Quartz,不需要考慮Y軸翻轉的問題
    [path addArcWithCenter:CGPointMake(50, 50) radius:50 startAngle:0 endAngle:M_PI clockwise:YES];
    //使用applyTransform函數來轉移坐標的Transform,這樣我們不用按照實際顯示做坐標計算
    [path applyTransform:CGAffineTransformMakeTranslation(50, 50)];
    //設置繪畫屬性
    [[UIColor blueColor] setStroke];
    [path setLineWidth:2];
    //執行繪畫
    [path stroke];
    
    //從Context中獲取圖像,並顯示在界面上
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    UIImageView *imgView = [[UIImageView alloc] initWithImage:img];
    [self.view addSubview:imgView];
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM