亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

[iOSUI進階-0]Quiartz2D

2019-11-14 19:42:09
字體:
來源:轉載
供稿:網友
A.簡介
1. 需要掌握的
  • drawRect:方法的使用
  • 常見圖形的繪制:線條、多邊形、圓
  • 繪圖狀態的設置:文字顏色、線寬等
  • 圖形上下文狀態的保存與恢復
  • 圖形上下文棧

1.基本圖形繪制
* 線段(線寬、線段樣式)
* 矩形(空心、實心、顏色)
* 三角形、梯形等形狀
* 橢圓/圓
* 圓弧
* 文字繪制
* 圖片繪制(pattern)
* 圖形上下文棧

2.練習(畫人)
3.模仿UIImageView
4.自定義checkbox
5.圖片裁剪
6.圖片水印
7.條紋背景
8.截圖
 
 
2.概念
Quartz 2D是一個二維繪圖引擎,同時支持iOS和Mac系統
Quartz 2D能完成的工作
  • 繪制圖形 : 線條/三角形/矩形/圓/弧等
  • 繪制文字
  • 繪制/生成圖片(圖像)
  • 讀取/生成PDF
  • 截圖/裁剪圖片
  • 自定義UI控件
  • … …
 
Quartz 2D能做很多強大的事情,例如
  • 裁剪圖片
  • 涂鴉/畫板
  • 手勢解鎖
 
B.Quartz2D在iOS開發中的價值
  • 為了便于搭建美觀的UI界面,iOS提供了UIKit框架,里面有各種各樣的UI控件
  • UILabel:顯示文字
  • UIImageView:顯示圖片
  • UIButton:同時顯示圖片和文字(能點擊)
  • … …

利用UIKit框架提供的控件,拼拼湊湊,能搭建和現實一些簡單、常見的UI界面

但是,有些UI界面極其復雜、而且比較個性化,用普通的UI控件無法實現,這時可以利用Quartz2D技術將控件內部的結構畫出來,自定義控件的樣子

其實,iOS中大部分控件的內容都是通過Quartz2D畫出來的

因此,Quartz2D在iOS開發中很重要的一個價值是:自定義view(自定義UI控件)
 
C.圖形上下文
圖形上下文(Graphics Context):是一個CGContextRef類型的數據

圖形上下文的作用
保存繪圖信息、繪圖狀態
決定繪制的輸出目標(繪制到什么地方去?)
(輸出目標可以是PDF文件、Bitmap或者顯示器的窗口上)
Image(270)
相同的一套繪圖序列,指定不同的Graphics Context,就可將相同的圖像繪制到不同的目標上
 
D.Quartz2D提供了以下幾種類型的Graphics Context
Bitmap Graphics Context
PDF Graphics Context
Window Graphics Context
Layer Graphics Context
PRinter Graphics Context
 
Image(271)
 
E.使用
1.自定義view
如何利用Quartz2D自定義view?(自定義UI控件)

如何利用Quartz2D繪制東西到view上?
首先,得有圖形上下文,因為它能保存繪圖信息,并且決定著繪制到什么地方去
其次,那個圖形上下文必須跟view相關聯,才能將內容繪制到view上面

自定義view的步驟
新建一個類,繼承自UIView
實現- (void)drawRect:(CGRect)rect方法,然后在這個方法中
取得跟當前view相關聯的圖形上下文
繪制相應的圖形內容
利用圖形上下文將繪制的所有內容渲染顯示到view上面
 
2. drawRect:
為什么要實現drawRect:方法才能繪圖到view上?
因為在drawRect:方法中才能取得跟view相關聯的圖形上下文

drawRect:方法在什么時候被調用?
當view第一次顯示到屏幕上時(被加到UIWindow上顯示出來)
調用view的setNeedsDisplay或者setNeedsDisplayInRect:時
 
Image(272)
 
3.Quartz2D須知
Quartz2D的API是純C語言的

Quartz2D的API來自于Core Graphics框架


數據類型和函數基本都以CG作為前綴
CGContextRef
CGPathRef
CGContextStrokePath(ctx);
……
 
4.drawRect:中取得的上下文
在drawRect:方法中取得上下文后,就可以繪制東西到view上

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

View之所以能顯示東西,完全是因為它內部的layer
 
5.Quartz2D繪圖的代碼步驟
獲得圖形上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();

拼接路徑(下面代碼是搞一條線段)
CGContextMoveToPoint(ctx, 10, 10);
CGContextAddLineToPoint(ctx, 100, 100);

繪制路徑
CGContextStrokePath(ctx); // CGContextFillPath(ctx);
 
6.常用拼接路徑函數
新建一個起點
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)
 
7.常用繪制路徑函數
Mode參數決定繪制的模式
void CGContextDrawPath(CGContextRef c, CGPathDrawingMode mode)

繪制空心路徑
void CGContextStrokePath(CGContextRef c)

繪制實心路徑
void CGContextFillPath(CGContextRef c)

提示:一般以CGContextDraw、CGContextStroke、CGContextFill開頭的函數,都是用來繪制路徑的
 
F.小練習
1.畫線段
(1)新建single view application,拖入一個view,創建一個class并設置
7C034679-1E00-4A8F-A576-62B4471DE619
 
(2)在自定義的view class 中實現drawRect:方法
 1 //重寫drawRect: 2 - (void)drawRect:(CGRect)rect { 3     // 1.獲得圖形上下文 4     CGContextRef ctx = UIGraphicsGetCurrentContext(); 5     6     // 2.拼接圖形 7     // 2.1設置一個起點 8     CGContextMoveToPoint(ctx, 10, 10); 9    10     // 2.2添加一條線段,是從(10,10)到(100,100)11     CGContextAddLineToPoint(ctx, 100, 100);12    13     // 2.3從上次的位置開始再添加一條線段,是從(100,100)到(150,40)14     CGContextAddLineToPoint(ctx, 150, 40);15    16     // 2.4最后畫一條直線連接會原處,形成一個三角形17 //    CGContextAddLineToPoint(ctx, 10, 10);18     CGContextClosePath(ctx); // 回到起點19    20     // 3.渲染顯示到view上面21     CGContextStrokePath(ctx);22 }
 
Image(273)
 
2.畫矩形
 1 - (void)drawRect:(CGRect)rect { 2     // 1.獲得上下文 3     CGContextRef ctx = UIGraphicsGetCurrentContext(); 4     5     // 2.畫四邊形 6     CGContextAddRect(ctx, CGRectMake(10, 10, 80, 100)); 7     8     // 繪制空心圖形 9 //    CGContextStrokePath(ctx);10    11     // 繪制實心圖形12     CGContextFillPath(ctx);13 }
 
Image(274)
 
3.畫圓
 1 - (void) drawRound { 2     // 1.獲得上下文 3     CGContextRef ctx = UIGraphicsGetCurrentContext(); 4     5     // 2.1畫圓 6     CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 100, 100)); 7     8     // 2.2橢圓 9     CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 150, 100));10    11     // 渲染12     CGContextStrokePath(ctx);13 }
 
Image(275)
 
 
4.畫圓弧
 1 - (void) drawArc { 2     // 1.獲得上下文 3     CGContextRef ctx = UIGraphicsGetCurrentContext(); 4     5     // 2.圓弧 6     // X軸正方向為0角度,最后一個參數1代表逆時針方向 7     CGContextAddArc(ctx, 100, 100, 50, 0, -M_PI, 1); 8     9     // 渲染10     CGContextStrokePath(ctx);11 }

 

Image(276)
 
1     // 2.圓弧2     // X軸正方向為0角度,最后一個參數1代表逆時針方向3     CGContextAddArc(ctx, 100, 100, 50, 0, -M_PI, 0);

 

Image(277)
 
 
5.畫文字
 1 - (void) drawText { 2     // 1.獲得上下文 3     CGContextRef ctx = UIGraphicsGetCurrentContext(); 4     5     // 2.畫上文字 6     /** 7      * 如果使用已經過期的方法 CGContextShowText,由于CG畫板是以左下角為零點,所以字會上下顛倒過來 8      */ 9     NSString *text = @"hello, 你好啊";10 //    [text drawAtPoint:CGPointZero withAttributes:nil];11    12     CGRect r = CGRectMake(50, 50, 100, 100);13     CGContextAddRect(ctx, r);14     CGContextFillPath(ctx);15    16     NSMutableDictionary *dict = [NSMutableDictionary dictionary];17     dict[NSForegroundColorAttributeName] = [UIColor redColor]; // 前景色,就是字體顏色18     dict[NSFontAttributeName] = [UIFont systemFontOfSize:20]; // 字體19     [text drawInRect:r withAttributes:dict];20    21     // 渲染22     CGContextStrokePath(ctx);23 }
 
Image(278)
 
6.畫圖片
(1)使用已經封裝好,不用手動轉換坐標的方法
 1 - (void) drawImg { 2     // 1.獲得上下文 3     CGContextRef ctx = UIGraphicsGetCurrentContext(); 4     5     // 取得圖片 6     UIImage *img = [UIImage imageNamed:@"M4"]; 7     8     // 畫上圖片 9 //    [img drawAtPoint:CGPointZero]; // 原圖大小,可能顯示不全10     [img drawInRect:CGRectMake(0, 0, 100, 200)]; // 填充方式默認是拉伸11    12     // 渲染13     CGContextStrokePath(ctx);14 }
 
(2)填充方式
a.drawAtPoint 默認是原圖
    [img drawAtPoint:CGPointZero]; // 原圖大小,可能顯示不全
Image(279)
 
b.drawInRect 是拉伸
    [img drawInRect:CGRectMake(0, 0, 100, 200)]; // 填充方式默認是拉伸
Image(280)
 
c.drawaspetternInRect
 1 - (void) drawImg { 2     // 1.獲得上下文 3     CGContextRef ctx = UIGraphicsGetCurrentContext(); 4    5     // 取得圖片 6     UIImage *img = [UIImage imageNamed:@"M4Mini"]; // 小圖 7   8     // 畫上圖片 9     [img drawAsPatternInRect:CGRectMake(0, 0, 200, 200)]; // 重復,可以用來做花紋10   11     // 渲染12     CGContextStrokePath(ctx);13 }
 
(3)文字水印
 1 - (void) drawImg { 2     // 1.獲得上下文 3     CGContextRef ctx = UIGraphicsGetCurrentContext(); 4     5     // 取得圖片 6     UIImage *img = [UIImage imageNamed:@"M4"]; // 大圖 7 //    UIImage *img = [UIImage imageNamed:@"M4Mini"]; // 小圖 8     9     // 畫上圖片10 //    [img drawAtPoint:CGPointZero]; // 原圖大小,可能顯示不全11     [img drawInRect:CGRectMake(0, 0, 100, 200)]; // 填充方式默認是拉伸12 //    [img drawAsPatternInRect:CGRectMake(0, 0, 200, 200)]; // 重復,可以用來做花紋13    14     // 文字15     NSString *text = @"這是一個美女";16     [text drawInRect:CGRectMake(0, 0, 100, 30) withAttributes:nil];17    18     // 渲染19     CGContextStrokePath(ctx);20 }

 

Image(281)
 
G.畫一個小黃人
利用基本的圖形描繪一個簡單地小黃人頭像
使用弧線、直線、橢圓
 
H.圖形上下文棧
為了在更改上下文設置后能夠完全、方便地恢復原來的設置
 1 - (void) contextStackDemo { 2     // 1.獲得上下文 3     CGContextRef ctx = UIGraphicsGetCurrentContext(); 4     5     // 2.存儲上下文 6     CGContextSaveGState(ctx); 7     8     // 3.設置上下文 9     CGContextSetLineCap(ctx, kCGLineCapRound);10     CGContextSetLineWidth(ctx, 10);11     [[UIColor redColor] set];12    13     // 4.畫第一條直線14     CGContextMoveToPoint(ctx, 10, 10);15     CGContextAddLineToPoint(ctx, 100, 100);16    17     // 渲染18     CGContextStrokePath(ctx);19    20     // 5.恢復上下文21     CGContextRestoreGState(ctx);22    23     // 6.第二條直線24     CGContextMoveToPoint(ctx, 100, 10);25     CGContextAddLineToPoint(ctx, 10, 100);26    27     // 渲染28     CGContextStrokePath(ctx);29 }
 
Image(282)
 
 
I.矩陣操作 裁剪
1.矩陣旋轉、縮放、移動操作
 1 - (void) testCTM { 2     CGContextRef ctx = UIGraphicsGetCurrentContext(); 3     4     CGContextSaveGState(ctx); 5     6     CGContextRotateCTM(ctx, M_PI_4 * 0.3); // 旋轉 7     CGContextScaleCTM(ctx, 0.5, 0.5); // 縮放 8     CGContextTranslateCTM(ctx, 100, 0); // 移動 9    10     CGContextAddRect(ctx, CGRectMake(10, 10, 100, 100));11     CGContextAddEllipseInRect(ctx, CGRectMake(100, 100, 60, 60));12    13     CGContextMoveToPoint(ctx, 200, 100);14     CGContextAddLineToPoint(ctx, 50, 200);15    16     CGContextStrokePath(ctx);17   18 }
 
Image(283)
 
2.裁剪
 1 - (void) testClip { 2     CGContextRef ctx = UIGraphicsGetCurrentContext(); 3     4     // 畫一個圓 5     CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 150, 150)); 6     7     // 裁剪 8     CGContextClip(ctx); 9    10     // 加上圖片11     UIImage *img = [UIImage imageNamed:@"a9ec8a13632762d0092abc3ca2ec08fa513dc619"];12     [img drawInRect:CGRectMake(0, 0, 150, 150)];13   14     CGContextStrokePath(ctx);    15 }
 
Image(284)
 
J.重繪(刷幀)
setNeedDisplay
1.通過一個滑塊控件來控制一個圓的動態大小
(1)在storyboard中描繪一個view和一個slider
Image(285)
 
(2)拖入slider的值變化事件和view到控制器,并使用自定義類為view的class
(3)在自定義UIView類中實現drawRect,在適當的地方調用setNeddDisplay重繪
MyView:
 1 - (void)setRadius:(CGFloat)radius { 2     _radius = radius; 3     4     // 調用重繪/刷幀方法 5     [self setNeedsDisplay]; 6 } 7  8 // 初始化控件的時候, drawRect只會調用一次 9 - (void)drawRect:(CGRect)rect {10     CGContextRef ctx = UIGraphicsGetCurrentContext();11    12     CGContextAddArc(ctx, 125, 125, self.radius, M_PI * 2, 0, 1);13     CGContextFillPath(ctx); // 實心圓14 }
 
ViewController:
 1 @interface ViewController () 2 - (IBAction)onSlideChange:(UISlider *)sender; 3 @property (weak, nonatomic) IBOutlet MyView *circleView; 4  5 @end 6  7 @implementation ViewController 8  9 - (void)viewDidLoad {10     [super viewDidLoad];11     // Do any additional setup after loading the view, typically from a nib.12 }13 14 - (void)didReceiveMemoryWarning {15     [super didReceiveMemoryWarning];16     // Dispose of any resources that can be recreated.17 }18 19 - (IBAction)onSlideChange:(UISlider *)sender {20     self.circleView.radius = sender.value * 100;21 }22 @end
 
可以用滑條控制圓的大小
Image(286)
 
2.下雪動畫
使用定時器 Timer
使用CADisplayLink
 1 - (void)awakeFromNib { 2     // 添加定時器 3 //    [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(setNeedsDisplay) userInfo:nil repeats:YES]; 4     5     // 刷新更快的工具 6     CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(setNeedsDisplay)]; // 創建 7     8     // 添加到消息循環,啟動 9     [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];10 }11 12 - (void)drawRect:(CGRect)rect {13     self.snowY += 1;14     if (self.snowY >= self.frame.size.height) {15         self.snowY = -100;16     }17     UIImage *image = [UIImage imageNamed:@"M2Mini"];18     [image drawAtPoint:CGPointMake(100, self.snowY)];19 }
 
3C60EE71-2F0B-400C-B383-1215BF964FA3
 
 
 

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品久久香蕉国产线看观看亚洲| 国产主播精品在线| 中国china体内裑精亚洲片| 亚洲国产97在线精品一区| 亚洲色图综合久久| 久久视频在线直播| 欧美激情亚洲激情| 欧美最猛性xxxxx(亚洲精品)| 国产精品啪视频| 青青久久av北条麻妃海外网| 国产亚洲欧洲黄色| 日韩欧美中文第一页| 国产精品91视频| 久热精品视频在线| 亚洲天堂视频在线观看| 国产精彩精品视频| 欧美成aaa人片免费看| 久久精品2019中文字幕| 国产一区二区日韩| 日韩精品中文字幕在线播放| 日韩国产高清污视频在线观看| 亚洲精品中文字幕有码专区| 日韩精品亚洲精品| 清纯唯美亚洲激情| 91精品国产91久久久久| 国产欧美日韩中文字幕| 亚洲中国色老太| 国产不卡在线观看| 日韩免费av片在线观看| 久久久久日韩精品久久久男男| 欧美裸体男粗大视频在线观看| 欧美电影在线观看| 日韩中文在线观看| 欧美日韩中文字幕综合视频| 黄色一区二区在线| www.国产精品一二区| 亚洲欧美成人在线| 欧美性感美女h网站在线观看免费| 欧美理论电影网| 性色av一区二区三区在线观看| 国产精品18久久久久久麻辣| 国产精品小说在线| 97人洗澡人人免费公开视频碰碰碰| 91精品国产高清自在线看超| 欧美午夜激情小视频| 欧美日韩激情视频| 欧美激情精品久久久久久| 亚洲人精品午夜在线观看| 国内免费久久久久久久久久久| 欧美做爰性生交视频| 91综合免费在线| 欧美国产欧美亚洲国产日韩mv天天看完整| 欧美日韩国产精品| 4k岛国日韩精品**专区| 中文字幕国产精品久久| 亚洲二区中文字幕| 成人国产精品免费视频| 久久久爽爽爽美女图片| 亚洲一二在线观看| 久久久www成人免费精品| 国产午夜精品一区二区三区| 亚洲第一区中文99精品| 久久亚洲国产精品成人av秋霞| 97国产在线观看| 日韩电影中文字幕| 欧美另类99xxxxx| 国产亚洲一区精品| 久久亚洲国产成人| 91久久久久久久一区二区| 亚洲精品久久7777777| 亚洲第一精品福利| 亚洲欧美自拍一区| 在线日韩第一页| 亚洲精品v天堂中文字幕| 亚洲精品美女在线观看| 久久久女女女女999久久| 日韩av影片在线观看| 国产97人人超碰caoprom| 日韩成人激情视频| 91亚洲精品久久久久久久久久久久| 98精品国产高清在线xxxx天堂| 日韩hd视频在线观看| 日韩av中文字幕在线免费观看| 亚洲欧美一区二区激情| 日韩高清免费观看| 狠狠久久五月精品中文字幕| 奇米成人av国产一区二区三区| 国产国语videosex另类| 黑人欧美xxxx| 亚洲奶大毛多的老太婆| 国产成人精品网站| 日韩精品亚洲元码| 亚洲欧美国产高清va在线播| 国产精品精品视频| 久久91亚洲精品中文字幕奶水| 日韩欧美一区二区三区| 在线精品国产成人综合| 亚洲欧美日韩精品久久奇米色影视| 91天堂在线视频| 亚洲精品一区中文字幕乱码| 国产精品一区二区久久久| y97精品国产97久久久久久| 国产极品精品在线观看| 国产九九精品视频| 欧美激情精品久久久久久黑人| 亚洲国产精品大全| 91免费的视频在线播放| 久久香蕉精品香蕉| 成人av色在线观看| 日韩中文理论片| 神马国产精品影院av| 亚洲男人天堂古典| 欧美第一淫aaasss性| 中文字幕av一区| 中文字幕一精品亚洲无线一区| www国产91| 久久国产精彩视频| 成人免费视频网址| 久久久999精品视频| 97超级碰在线看视频免费在线看| 久久久久久网址| 欧美激情第6页| 国产国语刺激对白av不卡| 91国产精品视频在线| 黑人狂躁日本妞一区二区三区| 国产在线日韩在线| 国产精品欧美亚洲777777| 亚洲欧美日韩中文在线| 欧美激情在线观看视频| 26uuu日韩精品一区二区| 黄色精品一区二区| 欧美黑人国产人伦爽爽爽| 538国产精品一区二区在线| 久久91亚洲人成电影网站| 亚洲999一在线观看www| 久久精品国产亚洲精品2020| 日韩av网址在线| 国产精品视频永久免费播放| 日韩中文字幕不卡视频| 91chinesevideo永久地址| 亚洲天堂视频在线观看| 66m—66摸成人免费视频| 日韩日本欧美亚洲| 国产日韩欧美在线视频观看| 亚洲国产成人久久| 狠狠色噜噜狠狠狠狠97| 青青久久av北条麻妃海外网| 国产一区二区三区在线免费观看| 精品免费在线观看| 色综合天天狠天天透天天伊人| 日韩麻豆第一页| 亚洲成avwww人| 国产精品美女www爽爽爽视频| 欧美日韩不卡合集视频| 欧美成人一区二区三区电影| 日韩美女免费视频| 欧美一区三区三区高中清蜜桃| 91久久嫩草影院一区二区| 在线丨暗呦小u女国产精品| 国产精品久久久久9999| 2019国产精品自在线拍国产不卡| 国产精品91在线观看| 国产精品视频一区国模私拍| 国产成人精品免高潮费视频|