iOS開發中的繪圖-Quartz2D-

來源:互聯網
上載者:User

iOS開發中的繪圖-Quartz2D-

 

什麼是Quartz2D

Quartz 2D是一個二維繪圖引擎,同時支援iOS和Mac系統

作用
Quartz 2D能完成的工作繪製圖形 : 線條三角形矩形圓弧等繪製文字繪製產生圖片(映像)讀取產生PDF裁剪圖片自訂UI控制項… 
Quartz2D在iOS開發中的價值
為了便於搭建美觀的UI介面,iOS提供了UIKit架構,裡面有各種各樣的UI控制項 UILabel:顯示文字 UIImageView:顯示圖片

UIButton:同時顯示圖片和文字(能點擊)
… …

利用UIKit架構提供的控制項,拼拼湊湊,能搭建和現實一些簡單、常見的UI介面

但是,有些UI介面極其複雜、而且比較個人化,用普通的UI控制項無法實現,這時可以利用Quartz2D技術將控制項內部的結構畫出來,自訂控制項的樣子 其實,iOS中大部分控制項的內容都是通過Quartz2D畫出來的,因此,Quartz2D在iOS開發中很重要的一個價值是:自訂view(自訂UI控制項)
基本圖形繪製線段(線寬、線段樣式、線條顏色)
注意點:畫線條只能通過空心樣式畫。CGContextStrokePath(ctx);
樣本
-(void)drawLine{    //1.獲得圖形上下文    CGContextRef ctx = UIGraphicsGetCurrentContext();    //2.拼接圖形(路徑)    //畫一條直線    //設定起始位置    CGContextMoveToPoint(ctx, 10, 10);    //添加一條線段到點(100,100)    CGContextAddLineToPoint(ctx, 100, 100);    //設定直線的寬度(黃色)    //CGContextSetRGBStrokeColor(ctx, 0, 1, 0, 1);    //set : 同時設定為空白心和實心顏色    //stroke : 設定空心顏色    //fill : 設定失心顏色    [[UIColor yellowColor]set];    //設定直線的寬度    CGContextSetLineWidth(ctx, 10);    //設定直線開頭的樣式(圓)    CGContextSetLineCap(ctx, kCGLineCapRound);    //設定直線轉折點的樣式(圓)    CGContextSetLineJoin(ctx, kCGLineJoinRound);    //3.渲染顯示到View上面    CGContextStrokePath(ctx);}
三角形樣本
-(void)drawTriangle{    //1.獲得圖形上下文    CGContextRef ctx = UIGraphicsGetCurrentContext();    //2.拼接圖形(路徑)    //畫一個三角形    //設定起始位置    CGContextMoveToPoint(ctx, 0, 0);    //添加一條線段到點(100,100)    CGContextAddLineToPoint(ctx, 100, 100);    CGContextAddLineToPoint(ctx, 120, 20);    CGContextClosePath(ctx);    //設定直線的寬度(紅色)    [[UIColor redColor]set];    //設定直線的寬度    CGContextSetLineWidth(ctx, 10);    //設定直線轉折點的樣式(切面)    CGContextSetLineJoin(ctx, kCGLineJoinBevel);    //3.渲染顯示到View上面    CGContextStrokePath(ctx);}
矩形(空心、實心、顏色)多種方法畫矩形
 * 方式一 // 1.擷取上下文      CGContextRef ctx = UIGraphicsGetCurrentContext(); // 2.繪製四條線條        CGContextMoveToPoint(ctx, 10, 10);        CGContextAddLineToPoint(ctx, 100, 10);        CGContextAddLineToPoint(ctx, 100, 100);        CGContextAddLineToPoint(ctx, 10, 100);        CGContextClosePath(ctx); //3.渲染        CGContextStrokePath(ctx);*方式二// 1.擷取上下文        CGContextRef ctx = UIGraphicsGetCurrentContext();// 2.繪製        CGContextAddRect(ctx, CGRectMake(10, 10, 100, 100));//3.渲染        CGContextStrokePath(ctx);* 方式三// 1.擷取上下文        CGContextRef ctx = UIGraphicsGetCurrentContext(); // 2.繪製並渲染        CGContextStrokeRect(ctx, CGRectMake(10, 10, 100, 100)); * 方式四 // 1.擷取上下文        CGContextRef ctx = UIGraphicsGetCurrentContext(); // 2.建立路徑        CGMutablePathRef path = CGPathCreateMutable();        CGPathAddRect(path,NULL, CGRectMake(10, 10, 100, 100)); // 3.添加路徑到上下文        CGContextAddPath(ctx, path);        CGPathRelease(path); // 4.渲染        CGContextStrokePath(ctx); * 方式五 UIBezierPath *path = [UIBezierPathbezierPathWithRect:CGRectMake(10, 10, 100, 100)]; [path stroke];
橢圓圓圓弧餅狀圖畫圓弧方法說明:
void CGContextAddArc ( CGContextRef c, CGFloat x,             //圓心的x座標 CGFloat y,    //圓心的x座標 CGFloat radius,   //圓的半徑 CGFloat startAngle,    //開始弧度 CGFloat endAngle,   //結束弧度 int clockwise          //0表示順時針,1表示逆時針);
-(void)drawCircle{    //1.獲得圖形上下文    CGContextRef ctx = UIGraphicsGetCurrentContext();    //2.拼接圖形    //畫圓    CGContextAddEllipseInRect(ctx, CGRectMake(50, 50, 100, 100));    //設定寬度    CGContextSetLineWidth(ctx, 10);    //設定顏色    [[UIColor purpleColor]set];    //3.渲染到View    CGContextStrokePath(ctx);}

假如想建立一個完整的圓圈,那麼開始弧度就是0 結束弧度是2pi
最後,函數執行完後,current point就被重設為(x,y).

還有一點要注意的是,假如當前path已經存在一個subpath,
那麼這個函數執行的另外一個效果是會有一條直線,從current point到弧的起點。

文字繪製和圖片繪製(pattern)繪製文字和圖片不要使用C語言函數。原因如下:Quarz2D 繪圖座標系和 UIKit 座標系不一致,導致使用 C 語言函數繪文字和圖片就會出現文字和圖片顛倒的現象,需要通過寫代碼調整,要利用到數學中矩陣的知識。 使用 C 語言函數繪製文字和圖片代碼複雜且函數不好理解。非常麻煩。圖形上下文(Graphics Context)簡介

圖形上下文(Graphics Context):是一個CGContextRef類型的資料

圖形上行下文的作用儲存繪圖資訊、繪圖狀態 決定繪製的輸出目標(繪製到什麼地方去?)
(輸出目標可以是PDF檔案、Bitmap或者顯示器的視窗上)

相同的一套繪圖序列,指定不同的Graphics Context,就可將相同的映像繪製到不同的目標上

自訂View如何利用Quartz2D繪製東西到view上?首先,得有圖形上下文,因為它能儲存繪圖資訊,並且決定著繪製到什麼地方去 其次,那個圖形上下文必須跟view相關聯,才能將內容繪製到view上面自訂view的步驟建立一個類,繼承自UIView 實現- (void)drawRect:(CGRect)rect方法,然後在這個方法中 取得跟當前view相關聯的圖形上下文 繪製相應的圖形內容 利用圖形上下文將繪製的所有內容渲染顯示到view上面drawRect:為什麼要實現drawRect:方法才能繪圖到view上?因為在drawRect:方法中才能取得跟view相關聯的圖形上下文drawRect:方法在什麼時候被調用?當view第一次顯示到螢幕上時(被加到UIWindow上顯示出來)
調用view的setNeedsDisplay或者setNeedsDisplayInRect:時drawRect:中取得的上下文

在drawRect:方法中取得上下文後,就可以繪製東西到view上

View內部有個layer(圖層)屬性,drawRect:方法中取得的是一個Layer Graphics Context,因此,繪製的東西其實是繪製到view的layer上去了

View之所以能顯示東西,完全是因為它內部的layer

繪圖順序

常用拼接路徑函數
建立一個起點void CGContextMoveToPoint(CGContextRef c, CGFloat x, CGFloat y)添加新的線段到某個點void CGContextAddLineToPoint(CGContextRef c, CGFloat x, CGFloat y)添加一個矩形void CGContextAddRect(CGContextRef c, CGRect rect)添加一個橢圓void CGContextAddEllipseInRect(CGContextRef context, CGRect rect)添加一個圓弧void CGContextAddArc(CGContextRef c, CGFloat x, CGFloat y,  CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)
常用繪製路徑函數
Mode參數決定繪製的模式void CGContextDrawPath(CGContextRef c, CGPathDrawingMode mode)繪製空心路徑void CGContextStrokePath(CGContextRef c)繪製實心路徑void CGContextFillPath(CGContextRef c)提示:一般以CGContextDraw、CGContextStroke、CGContextFill開頭的函數,都是用來繪製路徑的
圖形上下文棧的操作
將當前的上下文copy一份,儲存到棧頂(那個棧叫做”圖形上下文棧”)void CGContextSaveGState(CGContextRef c)將棧頂的上下文出棧,替換掉當前的上下文void CGContextRestoreGState(CGContextRef c)
矩陣操作

利用矩陣操作,能讓繪製到上下文中的所有路徑一起發生變化

縮放
void CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy)

旋轉
void CGContextRotateCTM(CGContextRef c, CGFloat angle)

平移
void CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty)

Quartz2D的記憶體管理

使用含有“Create”或“Copy”的函數建立的對象,使用完後必須釋放,否則將導致記憶體泄露

使用不含有“Create”或“Copy”的函數擷取的對象,則不需要釋放

如果retain了一個對象,不再使用時,需要將其release掉

可以使用Quartz 2D的函數來指定retain和release一個對象。例如,如果建立了一個CGColorSpace對象,則使用函數CGColorSpaceRetain和CGColorSpaceRelease來retain和release對象。

也可以使用Core Foundation的CFRetain和CFRelease。注意不能傳遞NULL值給這些函數

常用樣本圖片浮水印浮水印:在圖片上加的防止他人盜圖的半透明logo、文字、表徵圖

浮水印的作用

告訴你這個圖片從哪來的
主要是一些網站為了著作權問題、廣告而添加的

有時候,在手機用戶端app中也需要用到浮水印技術

比如,使用者拍完照片後,可以在照片上打個浮水印,標識這個圖片是屬於哪個使用者的

實現方式:利用Quartz2D,將浮水印(文字、LOGO)畫到圖片的右下角

核心代碼
#import UIImage+WHJ.h@implementation UIImage (WHJ)+(instancetype)waterImageWithBg:(NSString *)bg logo:(NSString * )logo{    UIImage *bgImage = [UIImage imageNamed:@scene];    //1.建立一個基於位元影像的上下文(開啟一個基於位元影像的上下文)    //size: 新圖片的尺寸    //opaque : 透明. NO為不透明,YES為透明    //scale : 縮放    //這段代碼過後就相當於建立一個新的bitmap,也就是新的UImage對象    UIGraphicsBeginImageContextWithOptions(bgImage.size, NO, 0.0);    //1.畫背景    [bgImage drawInRect:CGRectMake(0, 0, bgImage.size.width, bgImage.size.height)];    //3.畫右下角的浮水印    UIImage *waterImage = [UIImage imageNamed:@logo];    CGFloat margin = 5;    CGFloat scale = 0.5;    CGFloat waterW = waterImage.size.width * scale;    CGFloat waterH = waterImage.size.height * scale;    CGFloat waterX = bgImage.size.width - waterW - margin;    CGFloat waterY = bgImage.size.height - waterH -margin;    [waterImage drawInRect:CGRectMake(waterX, waterY, waterW, waterH)];    //4.從上下文取得製作完畢的UIImage對象    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    //5.結束上下文    UIGraphicsEndImageContext();    return newImage;}@end
可以將圖片匯出為png圖片
    //6.顯示到View    self.iconView.image = newImage;    //7.將image壓縮為PNG格式的位元據    NSData * data = UIImagePNGRepresentation(newImage);    //8.寫入檔案    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject]stringByAppendingPathComponent:@new.png];    [data writeToFile:path atomically:YES];    //    NSLog(@%@,path);
圖片裁剪將普通的圖片裁剪為圓形
    //1.獲得圖片    UIImage *image = [UIImage imageNamed:@abc];    //2.開始圖片上下文    UIGraphicsBeginImageContext(image.size);    //畫圓    //這段代碼獲得的上下文就是上一段代碼開始的上下文    CGContextRef ctx = UIGraphicsGetCurrentContext();    CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, image.size.width, image.size.height));    CGContextClip(ctx);    //3.繪製圖片    [image drawAtPoint:CGPointZero];    //4.獲得圖片    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    self.iconView.image = newImage;    //5.關閉上下文    UIGraphicsEndImageContext();
截屏截取螢幕上的內容
+(instancetype)catchImageWithView:(UIView *)view{    //開啟圖形上下文    UIGraphicsBeginImageContext(view.frame.size);    //將控制器中內容相關的內容渲染到View中    [view.layer renderInContext:UIGraphicsGetCurrentContext()];    //從圖形上下文獲得圖片    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    //關閉上下文    UIGraphicsEndImageContext();    return newImage;}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.