Quartz2D
簡(jiǎn)介
Quartz2D是二維(平面)的繪圖引擎(經(jīng)包裝的函數(shù)庫(kù),方便開發(fā)者使用。也就是說(shuō)蘋果幫我們封裝了一套繪圖的函數(shù)庫(kù))
同時(shí)支持iOS和Mac系統(tǒng)開發(fā),用Quartz2D寫的同一份代碼,既可以運(yùn)行在iphone上又可以運(yùn)行在mac上,可以跨平臺(tái)開發(fā)。
Quartz 2D能完成的工作
繪制圖形 : 線條\三角形\矩形\圓\弧等
繪制文字
繪制\生成圖片(圖像)
讀取\生成PDF
截圖\裁剪圖片
自定義UI控件
.....
Quartz2D在iOS開發(fā)中的價(jià)值
為了便于搭建美觀的UI界面,iOS提供了UIKit框架,里面有各種各樣的UI控件 UILabel:顯示文字 UIImageView:顯示圖片 UIButton:同時(shí)顯示圖片和文字(能點(diǎn)擊) … …
利用UIKit框架提供的控件,拼拼湊湊,能搭建和現(xiàn)實(shí)一些簡(jiǎn)單、常見的UI界面,但是,有些UI界面極其復(fù)雜、而且比較個(gè)性化,用普通的UI控件無(wú)法實(shí)現(xiàn),這時(shí)可以利用Quartz2D技術(shù)將控件內(nèi)部的結(jié)構(gòu)畫出來(lái),自定義控件的樣子,iOS中大部分控件的內(nèi)容都是通過(guò)Quartz2D畫出來(lái)的,因此,Quartz2D在iOS開發(fā)中很重要的一個(gè)價(jià)值是:自定義view(自定義UI控件)
自定義View
圖形上下文(Graphics Context):是一個(gè)CGContextRef類型的數(shù)據(jù)
圖形上下文的作用
保存繪圖信息、繪圖狀態(tài) -決定繪制的輸出目標(biāo)(繪制到什么地方去?) (輸出目標(biāo)可以是PDF文件、Bitmap或者顯示器的窗口上) 相同的一套繪圖序列,指定不同的Graphics Context,就可將相同的圖像繪制到不同的目標(biāo)上
自定義view的步驟
新建一個(gè)類,繼承自UIView
實(shí)現(xiàn)- (void)drawRect:(CGRect)rect方法,然后在這個(gè)方法中
取得跟當(dāng)前view相關(guān)聯(lián)的圖形上下文
繪制相應(yīng)的圖形內(nèi)容
利用圖形上下文將繪制的所有內(nèi)容渲染顯示到view上面
drawRect:方法
實(shí)現(xiàn)drawRect:方法才能繪圖到view,因?yàn)樵赿rawRect:方法中才能取得跟view相關(guān)聯(lián)的圖形上下文,
drawRect:方法在調(diào)用時(shí)間 當(dāng)view第一次顯示到屏幕上時(shí)(被加到UIWindow上顯示出來(lái)) 調(diào)用view的setNeedsDisplay或者setNeedsDisplayInRect:時(shí)
在drawRect:方法中取得上下文后,就可以繪制東西到view上
View內(nèi)部有個(gè)layer(圖層)屬性,drawRect:方法中取得的是一個(gè)Layer Graphics Context,因此,繪制的東西其實(shí)是繪制到view的layer上去了,View之所以能顯示東西,完全是因?yàn)樗鼉?nèi)部的layer
示例1畫直線
1> 獲取圖形上下文 CG:表示這個(gè)類在CoreGraphics框架里 Ref:引用 目前學(xué)的上下文都跟UIGraphics有關(guān),想獲取圖形上下文,首先敲UIGraphics。
2> 拼接路徑:一般開發(fā)中用貝塞爾路徑,里面封裝了很多東西,可以幫我畫一些基本的線段,矩形,圓等等。 創(chuàng)建貝塞爾路徑 起點(diǎn):moveToPoint 終點(diǎn):addLineToPoint
3> 把路徑添加到上下文 CGPath轉(zhuǎn)換:UIKit框架轉(zhuǎn)CoreGraphics直接CGPath就能轉(zhuǎn)
4> 把上下文渲染到視圖,圖形上下文本身不具備顯示功能。 PPT畫圖分析為什么要這樣做?首先獲取圖形上下文,然后描述路徑,把路徑添加到上下文,渲染到視圖,圖形上下文相當(dāng)于一個(gè)內(nèi)存緩存區(qū),在內(nèi)存里面操作是最快的,比直接在界面操作快多了。
在添加一根線 直接addLineToPoint,因?yàn)槁窂绞瞧唇拥?,默認(rèn)下一條線的起點(diǎn)是上一條線的終點(diǎn)。
畫兩跟不連接的線 1> 第二次畫的時(shí)候,重新設(shè)置起點(diǎn),然后畫線。一個(gè)路徑可以包含多條線段。 2> 新創(chuàng)建一個(gè)路徑,添加到上下文。開發(fā)中建議使用這種,比較容易控制每根線。
設(shè)置繪圖狀態(tài) 線段怎么加粗。 繪圖狀態(tài)調(diào)用順序:只要在渲染之前就好了,在渲染的時(shí)候才會(huì)去看繪圖的最終狀態(tài)。
// 1.獲取跟當(dāng)前view想關(guān)聯(lián)的上下文// 以后只要根上下文有關(guān),直接敲UIGraphics,一般都是以UIGraphics開頭// CG:CoreGraphics Ref:引用CGContextRefctx =UIGraphicsGetCurrentContext();// 2.繪制內(nèi)容,拼接路徑,繪制的內(nèi)容統(tǒng)稱為路徑// 在開發(fā)中一般使用貝塞爾路徑,UIKit框架UIBezierPath*path = [UIBezierPathbezierPath];// 設(shè)置起點(diǎn),移動(dòng)到某個(gè)位置[path moveToPoint:CGPointMake(50,50)];// 添加一根線到某個(gè)點(diǎn)[path addLineToPoint:CGPointMake(200,200)];// 一根路徑對(duì)象可以包含很多線段[path moveToPoint:CGPointMake(50,200)];// 默認(rèn)下一根線的起點(diǎn)在上一根線的終點(diǎn)[path addLineToPoint:CGPointMake(100,200)];// 3.把路徑添加到上下文,給上下文添加路徑以CGContextCGContextAddPath(ctx, path.CGPath);// 開發(fā)中,如果線段不連接,最好使用一根線對(duì)應(yīng)一個(gè)路徑對(duì)象// 描述第二根線//? ? path = [UIBezierPath bezierPath];////? ? // 設(shè)置起點(diǎn),移動(dòng)到某個(gè)位置//? ? [path moveToPoint:CGPointMake(200, 200)];////? ? // 添加一根線到某個(gè)點(diǎn)//? ? [path addLineToPoint:CGPointMake(100, 200)];////? ? CGContextAddPath(ctx, path.CGPath);// 4.把上下文內(nèi)容渲染到viewCGContextStrokePath(ctx);
示例2畫圓形
//Center:圓心//radius:半徑.//startAngle:開始角度//endAngle:結(jié)束角度//clockwise:CGPointcenter =CGPointMake(self.bounds.size.width*0.5,self.bounds.size.height*0.5);CGFloatradius =100;CGFloatstartA =0;//圓的0度角在圓的最右側(cè).CGFloatendA = -M_PI_2;UIBezierPath*path =? [UIBezierPathbezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];? ? [UIColorredColor] set];? ? [path stroke];
示例3畫文字,常見屬性
//我們要畫的文字NSString*str =@"我們要畫的文字";//開始繪制文字//? ? AtPoint:畫在哪個(gè)點(diǎn)上.//Attributes:文字的屬性.顏色,字體大小...NSMutableDictionary*dict = [NSMutableDictionarydictionary];//設(shè)置文字的顏色dict[NSForegroundColorAttributeName] = [UIColorredColor];//設(shè)置字體大小dict[NSFontAttributeName] = [UIFontsystemFontOfSize:50];//設(shè)置描邊的顏色dict[NSStrokeColorAttributeName] = [UIColorblueColor];//設(shè)置描邊的寬度dict[NSStrokeWidthAttributeName] = @1;NSShadow*shadow = [[NSShadowalloc] init];//設(shè)置陰影的偏移量shadow.shadowOffset=CGSizeMake(-10,10);//設(shè)置陰影的顏色shadow.shadowColor= [UIColorgreenColor];//設(shè)置陰影的模糊shadow.shadowBlurRadius=2;? ? dict[NSShadowAttributeName] = shadow;//drawAtPoint不會(huì)自動(dòng)換行//? ? [str drawAtPoint:CGPointZero withAttributes:dict];//drawInRect它會(huì)自動(dòng)的換行.[str drawInRect:self.boundswithAttributes:dict];
圖形上下文的矩陣操作
形變操作,必須得要在添加路徑之前進(jìn)行
計(jì)時(shí)器
CADisplayLink
//在繪圖當(dāng)中, 我們一般使用CADisplayLink.因?yàn)樗蛃etNeedsDisplay調(diào)用時(shí)機(jī)是一樣的,都是當(dāng)下一次屏幕刷新的時(shí)候調(diào)用.
//CADisplayLink//它是當(dāng)每次屏幕刷新的時(shí)候就會(huì)調(diào)用定時(shí)器方法.(每一秒種刷新60次)CADisplayLink*link = [CADisplayLinkdisplayLinkWithTarget:selfselector:@selector(update)];//想讓定時(shí)器工作,必須得要把它添加到主運(yùn)行循環(huán).[link addToRunLoop:[NSRunLoopmainRunLoop] forMode:NSDefaultRunLoopMode];
NSTimer
[NSTimerscheduledTimerWithTimeInterval:0.01target:selfselector:@selector(update) userInfo:nilrepeats:YES];
注意,在實(shí)際開發(fā)中視情況選擇使用
常用的拼接函數(shù)
新建一個(gè)起點(diǎn)voidCGContextMoveToPoint(CGContextRefc,CGFloatx,CGFloaty)添加新的線段到某個(gè)點(diǎn)voidCGContextAddLineToPoint(CGContextRefc,CGFloatx,CGFloaty)添加一個(gè)矩形voidCGContextAddRect(CGContextRefc,CGRectrect)添加一個(gè)橢圓voidCGContextAddEllipseInRect(CGContextRefcontext,CGRectrect)添加一個(gè)圓弧voidCGContextAddArc(CGContextRefc,CGFloatx,CGFloaty,CGFloatradius,CGFloatstartAngle,CGFloatendAngle,intclockwise)
常用繪制的函數(shù)
Mode參數(shù)決定繪制的模式
voidCGContextDrawPath(CGContextRefc,CGPathDrawingModemode)繪制空心路徑voidCGContextStrokePath(CGContextRefc)繪制實(shí)心路徑voidCGContextFillPath(CGContextRefc)提示:一般以CGContextDraw、CGContextStroke、CGContextFill開頭的函數(shù),都是用來(lái)繪制路徑的
矩陣操作
利用矩陣操作,能讓繪制到上下文中的所有路徑一起發(fā)生變化縮放voidCGContextScaleCTM(CGContextRefc,CGFloatsx,CGFloatsy)旋轉(zhuǎn)voidCGContextRotateCTM(CGContextRefc,CGFloatangle)平移voidCGContextTranslateCTM(CGContextRefc,CGFloattx,CGFloatty)
圖片水印技術(shù)
需求:在手機(jī)客戶端app中需要用到水印技術(shù),用戶拍完照片后,可以在照片上打個(gè)水印,標(biāo)識(shí)這個(gè)圖片是屬于哪個(gè)用戶的
實(shí)現(xiàn)方式:利用Quartz2D,將水?。ㄎ淖帧OGO)畫到圖片的右下角
核心代碼
開啟一個(gè)基于位圖的圖形上下文UIGraphicsBeginImageContextWithOptions(CGSizesize,BOOLopaque,CGFloatscale)從上下文中取得圖片(UIImage)UIImage*UIGraphicsGetImageFromCurrentImageContext();結(jié)束基于位圖的圖形上下文UIGraphicsEndImageContext();
水印PPT簡(jiǎn)介
圖片水印作用:防止他人盜取圖片,加一些Logo,生成一張新的圖片。
和繪圖一樣的生成新的圖片,需要拿到上下文做事情,這里也需要拿到上下文,生成一個(gè)新的圖片。
位圖上下文,在這個(gè)上下文畫東西,就能輸出到新的圖片上。
之前用的都是圖層上下文,系統(tǒng)會(huì)自動(dòng)創(chuàng)建,但是我們位圖上下文,需要我們手動(dòng)創(chuàng)建
總結(jié):只要不和view有關(guān)系的上下文,都需要我們手動(dòng)創(chuàng)建。
在哪獲取圖像上下文,viewDidLoad, 不需要拿到系統(tǒng)創(chuàng)建的圖層上下文,沒(méi)必要在drawRect方法里寫,直接viewDidLoad就行了。
UIGraphicsBeginImageContextWithOptions:(CGSize size, BOOL opaque, CGFloat scale)創(chuàng)建一個(gè)位圖上下文,而且這種方法得到的圖片最清晰。解釋參數(shù)(size:新圖片尺寸 opaque: YES:不透明 NO:透明 scale:0.0 不伸縮)
繪制內(nèi)容(圖片,文字)
獲取圖片:把位圖上下文的內(nèi)容生成一個(gè)圖片給你。
關(guān)閉上下文,不關(guān)閉一直占用著內(nèi)存。
顯示UIImageView上
保存圖片,寫到文件,UIImage不能寫,需要轉(zhuǎn)換成NSData二進(jìn)制數(shù)據(jù)
UIImageJPEGRepresentation:可以設(shè)置圖片質(zhì)量
UIImagePNGRepresentation:把圖片轉(zhuǎn)換成png格式的二進(jìn)制數(shù)據(jù),png格式默認(rèn)是最高清的。
寫到桌面
圖片裁剪
圖片裁剪
PPT分析思路:先設(shè)置裁剪區(qū)域,把圖片畫上去,超出裁剪區(qū)域的自動(dòng)裁剪掉。
加載舊圖片,根據(jù)舊圖片,獲取上下文尺寸。
上下文的尺寸 = 新圖片的尺寸
開啟一個(gè)多大的上下文?:和圖片尺寸一樣大,避免壓縮圖片。如果比圖片尺寸小,會(huì)壓縮圖片。
設(shè)置裁剪區(qū)域:正切于圖片的圓
繪制舊圖片
獲取新圖片
關(guān)閉上下文
//1.加載要裁剪的圖片UIImage*image = [UIImageimageNamed:@"阿貍頭像"];
//2.開啟一個(gè)跟圖片尺寸一樣大的位圖上下文UIGraphicsBeginImageContextWithOptions(image.size,NO,0);
//3.設(shè)置一個(gè)裁剪(寬度和高度都是等于原始圖片的寬高)UIBezierPath*path = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0, image.size.width, image.size.height)];//把路徑設(shè)置成裁剪區(qū)域[path addClip];
//4.把要裁剪的圖片繪制到上下文當(dāng)中.[image drawAtPoint:CGPointZero];
//5.從上下文當(dāng)中生成一張新的圖片UIImage*newImage =UIGraphicsGetImageFromCurrentImageContext();
//6.關(guān)閉上下文.UIGraphicsEndImageContext();self.imageV.image= newImage;
帶圓環(huán)裁剪:在裁剪的圖片外邊加個(gè)小圓環(huán)。
先畫一個(gè)大圓,在設(shè)置裁剪區(qū)域,把圖片畫上去,超出裁剪區(qū)域的自動(dòng)裁剪掉。
加載舊圖片,根據(jù)舊圖片,獲取上下文尺寸。
確定圓環(huán)寬度 borderW
上下文的尺寸 = 新圖片的尺寸
確定新的上下文尺寸: newImageW : oldImageW + 2borderW newImageH : oldImageH + 2borderW,
繪制大圓: 1.獲取上下文 2.添加路徑到上下文 3.設(shè)置大圓的顏色 = 圓環(huán)的顏色 4.渲染
設(shè)置裁剪區(qū)域,和圖片尺寸一樣大,只不過(guò),x,y不一樣,x=borderW,y=borderW.
繪制舊圖片
獲取新圖片
關(guān)閉上下文
抽分類,3個(gè)參數(shù),圖片名稱,圓環(huán)寬度,圓環(huán)顏色
可以創(chuàng)建給UIImage添加一個(gè)分類提供方法直接使用
//0.設(shè)置一個(gè)邊框?qū)挾?/1.加載圖片//2.開啟一個(gè)位圖上下文CGSizesize =CGSizeMake(image.size.width+2* boderW, image.size.height+2* boderW);UIGraphicsBeginImageContextWithOptions(size,NO,0);
//3.設(shè)置一個(gè)大圓的一個(gè)填充區(qū)域UIBezierPath*path = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0, size.width, size.height)];//設(shè)置邊框的顏色[color set];? ? [path fill];
//4.設(shè)置一個(gè)小圓裁剪區(qū)域path = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(boderW, boderW, image.size.width, image.size.height)];//把小圓設(shè)置成裁剪區(qū)域[path addClip];
//5.把原始圖片繪制到上下文當(dāng)中[image drawInRect:CGRectMake(boderW, boderW, image.size.width, image.size.height)];
//6.生成一張新的圖片UIImage*newImage =UIGraphicsGetImageFromCurrentImageContext();
//7.關(guān)閉上下文.UIGraphicsEndImageContext();returnnewImage;
圖片截屏
屏幕截圖:把屏幕的內(nèi)容截屏生成一張新的圖片
通常開發(fā)中,都是把控制器的內(nèi)容截屏,生成新的圖片
控制器根據(jù)view顯示
view根據(jù)layer圖層顯示
把layer渲染到位圖上下文
注意:圖層只能用渲染,圖片和文字可以用draw
渲染在新的圖片
開啟圖片上下文,和視圖一樣的尺寸
寫入桌面
抽分
//懶加載,當(dāng)使用才創(chuàng)建,可以節(jié)省內(nèi)存-(UIView*)cover{if(_cover ==nil) {//創(chuàng)建一個(gè)遮蓋UIView*cover = [[UIViewalloc] init];? ? ? ? cover.backgroundColor= [UIColorblackColor];? ? ? ? cover.alpha=0.7;? ? ? ? _cover = cover;? ? ? ? [self.viewaddSubview:cover];? ? }return_cover;}
- (void)viewDidLoad {? ? [superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.}
//當(dāng)手指拖動(dòng)的時(shí)候調(diào)用- (IBAction)pan:(UIPanGestureRecognizer*)pan {//獲取當(dāng)前手指所在的點(diǎn)CGPointcurP = [pan locationInView:self.imageV];//起點(diǎn)if(pan.state==UIGestureRecognizerStateBegan){//添加遮蓋,設(shè)置遮蓋的起點(diǎn).self.startP= curP;? ? }elseif(pan.state==UIGestureRecognizerStateChanged){//移動(dòng),確定遮蓋的尺寸//x軸偏移量CGFloatoffsetX = curP.x-self.startP.x;//Y 軸的偏移量CGFloatoffsetY = curP.y-self.startP.y;//改變遮蓋的尺寸self.cover.frame=CGRectMake(self.startP.x,self.startP.y, offsetX, offsetY);? ? }else if(pan.state==UIGestureRecognizerStateEnded){//松開//做裁剪
//開啟一個(gè)上下文.(跟圖片一樣大的上下文.)UIGraphicsBeginImageContextWithOptions(self.imageV.bounds.size,NO,0);
//在上下文當(dāng)中設(shè)置一個(gè)裁剪區(qū)域(就是當(dāng)前遮蓋的frame)UIBezierPath*path = [UIBezierPathbezierPathWithRect:self.cover.frame];
//設(shè)置裁剪區(qū)域[path addClip];//把UIImageView當(dāng)中的圖片繪制到上下文當(dāng)中.
//獲取當(dāng)前上下文CGContextRefctx =UIGraphicsGetCurrentContext();? ? ? [self.imageV.layerrenderInContext:ctx];
//生成一張新的圖片.UIImage*newImage =UIGraphicsGetImageFromCurrentImageContext();
//把位圖上下文關(guān)閉掉UIGraphicsEndImageContext();
//把UIImageView當(dāng)中的圖片重新賦值self.imageV.image= newImage;//移除遮蓋[self.coverremoveFromSuperview];? ? }}
手勢(shì)解鎖
分析界面有幾個(gè)控件:背景:UIImageView 白色圓圈:按鈕(點(diǎn)擊他,會(huì)出現(xiàn)另外一種圖片,按鈕可以設(shè)置不同狀態(tài)下的圖片。)單獨(dú)視圖:(畫線是有范圍的,當(dāng)超出view就不能畫線了)
HMLoadView:自定義視圖,在視圖一創(chuàng)建的時(shí)候,就添加9個(gè)按鈕。
在initWithCoder,initWithFrame方法添加按鈕。
九宮格布局:
tolcol =3計(jì)算row,col 按鈕的x,y跟col,row有關(guān)系,col = i % tolcol row = i / tolcol? 計(jì)算邊距 margin = (view.bounds.size.width- tolcol * btnW) / (tolcol +1)? btnX = margin + (btnW + margin) * col? btnY = (btnW + margin) * row
圓的選中
點(diǎn)擊按鈕就為選中的圖片怎么做?監(jiān)聽按鈕點(diǎn)擊。
不能addTarget: 不能及時(shí)顯示選中圖片。
監(jiān)聽touchBegin,判斷點(diǎn)在不在按鈕的frame上。
touchBegin不調(diào)用?原因:事件交給按鈕處理,應(yīng)該把事件交給解鎖視圖。讓按鈕不接收事件。
設(shè)置按鈕不允許交互,2個(gè)用處:1.不接收事件 2.取消高亮效果 一舉兩得
遍歷所有按鈕,看觸摸點(diǎn)在哪個(gè)按鈕上,就選中誰(shuí),CGRectContainsPoint 傳入的參數(shù)必須是同一個(gè)坐標(biāo)系
實(shí)現(xiàn)touchMove方法:因?yàn)槭种敢苿?dòng)的時(shí)候,也需要判斷點(diǎn)在不在按鈕上。
抽方法,因?yàn)閠ouchMove的方法里,也需要做同樣的事情。
1>pointWithTouches根據(jù)touches集合取出觸摸點(diǎn)2>buttonWithPoint根據(jù)觸摸點(diǎn),獲取觸摸按鈕
圓的連線
被選中按鈕之間都需要連線,還有一個(gè)多余的線
先把選中的按鈕全部連線,因?yàn)槎嘤嗟哪歉€是從最后一個(gè)按鈕的圓心開始畫,手指移動(dòng)在哪就畫哪。
搞個(gè)數(shù)組保存下所有選中按鈕,在drawRect方法中遍歷所有按鈕,連線
UIBezierPath畫線,不需要上下文。
需要多少個(gè)UIBezierPath對(duì)象?一個(gè),路徑都是連續(xù)的,不相連的,才需要?jiǎng)?chuàng)建新的UIBezierPath。
遍歷數(shù)組,描述路徑 1> 起點(diǎn):第一個(gè)按鈕的圓心 2> 添加一根線到其他按鈕的圓心
設(shè)置路徑的顏色和線寬
把所有路徑都描述完就,渲染一次就夠了。
[path stroke] 就能渲染到視圖上了。
畫多余的那根線,記住手指移動(dòng)的位置。
setNeedDisplay 因?yàn)閐rawRect只會(huì)調(diào)用一次,需要每次手指移動(dòng)的時(shí)候,都需要重繪。
touchBegin不調(diào)用setNeedDisplay,因?yàn)橹乩L也沒(méi)用,只有起點(diǎn)。
lineJoinStyle:有尖尖的東西,線段連接樣式的問(wèn)題,設(shè)置為平的。
已經(jīng)選中的按鈕,不需要再次選中,和畫線
手指抬起,取消所有選中按鈕,并且清空數(shù)組,清空線條
drawRect判斷下沒(méi)有選中數(shù)組,不需要畫線。
如何判斷用戶是否輸入正確?給選中按鈕綁定tag,遍歷所有選中按鈕,把tag拼接成一個(gè)字符串。
畫板
分析控件:ToolBar(不需要管里面子控件的frame),畫板view,自定義工具條(方便屏幕適配,能迅速固定里面子控件的位置)
自動(dòng)布局,四個(gè)約束確定一個(gè)控件
藍(lán)色按鈕:左,右,下,高固定
橘色按鈕:右,下固定,寬度和高度和藍(lán)色按鈕相等。
綠色按鈕:右,下,寬度和高度和橘色按鈕相等
繪圖思路:先描述路徑,在渲染,需要畫很多線條,最好每個(gè)線條保存到一個(gè)路徑里面。
繪圖功能
touchBegin設(shè)置畫線起點(diǎn):開始觸摸的點(diǎn)
創(chuàng)建UIBezierPath,貝塞爾路徑才能設(shè)置起點(diǎn)
touchMove:手指移動(dòng)到哪就畫哪,addLine到移動(dòng)的點(diǎn)
setNeedDisplay,路徑描述完了,就渲染到視圖就好了。
drawRect方法每次都會(huì)把之前的清掉,重新繪制
搞個(gè)數(shù)組保存上一次的,繪制多條線
設(shè)置線寬:每次滑動(dòng)滑塊,就改變下一次路徑的寬度
監(jiān)聽滑塊的值,把值傳遞給paintView,設(shè)置路徑的線寬。
不能在drawRect寫,會(huì)導(dǎo)致所有路徑都是一個(gè)線寬,應(yīng)該是每個(gè)路徑都記錄自己的線寬,而且線寬只需要設(shè)置一次,在路徑一創(chuàng)建的時(shí)候就設(shè)置。
設(shè)置顏色:
自定義UIBezierPath,保存顏色,實(shí)現(xiàn)一條路徑對(duì)應(yīng)一個(gè)顏色 輔助功能:
清屏:清空所有路徑數(shù)組
撤銷:移除最后一條路徑
橡皮擦:設(shè)置畫筆為白色
保存:
1> 把畫板內(nèi)容截屏
2> 把圖片保存到相冊(cè) UIImageWriteToSavedPhotosAlbum
3> 保存相冊(cè)的回調(diào)方法不能亂寫,必須按照規(guī)定 image:didFinishSavingWithError:contextInfo:
照片選擇
1> 通常都是去相冊(cè)里去照片
2> UIImagePickerController,就可以去手機(jī)相冊(cè)了
3> 用Modal,沒(méi)有導(dǎo)航控制器,不能push
4> 設(shè)置代理,獲取圖片
5> 把圖片傳遞給paintView
6> 添加到路徑,然后重繪。:畫圖片也需要順序的
照片處理
1>搞一個(gè)和畫板一樣的透明view,里面搞個(gè)UIImageView來(lái)顯示我們從照片庫(kù)選擇的圖片,然后對(duì)UIImageView進(jìn)行旋轉(zhuǎn),縮放等操作
2> UImageView不能放在layoutSubViews里面設(shè)置尺寸,因?yàn)橐O(shè)置他的形變,默認(rèn)會(huì)調(diào)用他父類的layoutSubViews,導(dǎo)致一些莫名其妙的原因
3> 在傳圖片的時(shí)候設(shè)置他的尺寸,和位置,讓他和圖片一樣的尺寸,顯示在中間
4> 長(zhǎng)按操作:在長(zhǎng)按結(jié)束的時(shí)候,做操作
1.默認(rèn)高亮狀態(tài),先變淺在恢復(fù),設(shè)置alpha
2.動(dòng)畫結(jié)束后,把自己截屏,傳給控制器里,在交給paintView顯示
3.需要移除父視圖,使命完成了,而且不移除,不能繪制東西,永遠(yuǎn)添加到paintView上面