Quartz 2d绘图
今天看了一下Quartz 2D繪圖,我只想說:不要把繪圖和動畫那些東西當(dāng)做一個(gè)很復(fù)雜的東西,其實(shí)只要你認(rèn)真看還是可以理解的。他們并不難。啰嗦了幾句,現(xiàn)在直接進(jìn)入正題:
前提是我們必須新建一個(gè)singleviewApplication。具體新建就不多說了,然后我們自己寫一個(gè)UIView的子類,然后創(chuàng)建子類加載到故事板中。(你也可以直接把故事板中的ViewControler的view的父類定義為你自己創(chuàng)建的類),然后我們的操作都是在drawRectangular:方法中實(shí)現(xiàn)的:(我采用的是直接修改View的父類為我自定義的類)
下面的就是代碼:我們一個(gè)一個(gè)來跟著代碼理解:
1、首先是最簡單的填充顏色:
- (void)drawRect:(CGRect)rect { // setFill設(shè)置填充的顏色[[UIColor redColor] setFill]; //隨后需要填充的顏色設(shè)置UIRectFill(rect); //用當(dāng)前的顏色進(jìn)行填充 }其中:
setFill方法:它的作用就是設(shè)置隨后填充操作用到的顏色。
UIRectFill():該方法就是用剛才設(shè)置的顏色進(jìn)行填充。
結(jié)果如下:
我們沒有在ViewController中的修改任何屬性,這只是在自定義的View中完成的。
2、使用UIRectFrame畫一個(gè)矩形:
- (void)drawRect:(CGRect)rect {//setStroke設(shè)置描邊的顏色 [[UIColor redColor] setStroke];CGRect frame = CGRectMake(20, 30, 100, 300);UIRectFrame(frame); }其中:
setStroke:是設(shè)置隨后描邊用到的顏色
UIRectFrame():根據(jù)指定的rect畫一個(gè)框架。
結(jié)果如下:
3、然后是NSString類的繪制文本方法:
- (void)drawRect:(CGRect)rect {NSString *s = [NSString stringWithFormat:@"zhangsan"];//這里面drawAtPoint就是繪制文本的方法[s drawAtPoint:CGPointMake(100, 300) withAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:34]}]; }運(yùn)行效果如下:
其中主要用的的方法就是drawAtPoint:那個(gè)方法
另外還有drawInRect方法。具體的方法介紹就不做過多介紹了。
4、畫三角形
- (void)drawRect:(CGRect)rect {CGContextRef context = UIGraphicsGetCurrentContext(); //創(chuàng)建圖形上下文CGContextSaveGState(context); //保存當(dāng)前圖形上下文設(shè)置CGContextMoveToPoint(context, 20, 20);CGContextAddLineToPoint(context, 40, 100);CGContextAddLineToPoint(context, 160, 20);CGContextClosePath(context);[[UIColor redColor] setFill];[[UIColor blackColor] setStroke];CGContextDrawPath(context, kCGPathFillStroke);
CGContextRestoreGState(context); //恢復(fù)圖形上下文設(shè)置 }
效果如下:
其中遇到了新的東西:CGContextRef。不要害怕遇到CG,其實(shí)很簡單。
首先,一句
CGContextRef context = UIGraphicsGetCurrentContext(); //創(chuàng)建圖形上下文創(chuàng)建了上下文,什么是上下文?????你可以直接把他理解成一個(gè)Quartz 2D的繪畫環(huán)境。
就是對每個(gè)的繪畫操作都需要一個(gè)繪畫環(huán)境,然后才能進(jìn)行繪畫操作。而UIGraphicsGetCurrentContext()就是獲取當(dāng)前的繪畫環(huán)境,
然后里面有:
CGContextMoveToPoint:就是繪畫的起始點(diǎn)。
CGContextAddLineToPoint:就是從剛才繪畫起始點(diǎn)到你在這個(gè)函數(shù)中指定的點(diǎn)。
最后用CGContextClosePath去封閉這三個(gè)點(diǎn)組成的圖形。這樣一個(gè)三角形就出來。
NO,NO,還需要CGContextDrawPath來進(jìn)行操作哦。它的作用是繪制當(dāng)前路徑用提供的繪制模型:這里用的kCGPathFillStroke,就是描邊填充模型,其他的模型讀者可以自己查看。
忘了,忘了。還有兩個(gè)方法沒介紹:
CGContextSaveGState(context):它的作用是為當(dāng)前的上下文保存一個(gè)復(fù)制。官方介紹是壓一份復(fù)制的當(dāng)前繪畫狀態(tài)到繪畫狀態(tài)棧中。也就是壓棧操作。
CGContextRestoreGState(context):設(shè)置當(dāng)前繪畫狀態(tài) 為最近保存的一份狀態(tài)。可以理解為出棧操作。
使用這兩個(gè)函數(shù)的原因:有事后需要多次改變圖形上下文對象的參數(shù),這樣兩次繪制就可能相互影響,這就好像拿著蠟筆畫畫,每一次只能拿一個(gè)。為了防止相互影響所以要保存上下文設(shè)置,繪制完成后我們在用restore那個(gè)函數(shù)回復(fù)圖形上下文。
5、Quartz路徑
Core Graphics中有4種基本圖元用于描述路徑:點(diǎn)、線、弧和貝塞爾(Bezier)曲線。前兩種都不用介紹了都見過,后面的貝塞爾曲線和弧需要說一下。
弧:可以由圓心點(diǎn)、半徑、起始角和結(jié)束角描述。圓是弧的一個(gè)特例。只需要這只起始角度為0,結(jié)束角度為360就可以了。
貝塞爾曲線:任何一條曲線都可以通過與他相切的控制線兩端的點(diǎn)的位置定義。具體我也不太理解,先沒看就。如果你理解的深刻可以給我說一下。
6、坐標(biāo)變換
首先要理解:在Quartz 2D中的坐標(biāo)系和UIKit坐標(biāo)系是相反的。什么意思勒?就是
Quartz 2D坐標(biāo)系原點(diǎn)在左下角,x向右為正方向,y向上為正方向
UIKit坐標(biāo)系原點(diǎn)在左上角,x向右為正方向,y向下為正方向。
現(xiàn)在就讓我們繼續(xù)看看坐標(biāo)變換把。
--------------------------------為了書寫方便下面的方法我直接提取出來了,只需要在drawRect:方法里面調(diào)用就行了--------------------------------
7、畫一張圖片:
//反向image - (void)drawImage {/*圖形的另一種操作就是變換:包括評議、縮放和旋轉(zhuǎn)等形式的變換Quartz 2D坐標(biāo)系和UIKit坐標(biāo)系是相反的。*/CGContextRef context = UIGraphicsGetCurrentContext();UIImage *image = [UIImage imageNamed:@"test"];CGImageRef cgImage = image.CGImage;CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);CGContextDrawImage(context, rect, cgImage);//由于坐標(biāo)系相反,所以圖形是返回來的。 }運(yùn)行一下看看:
這圖片怎么長這樣,我開始也納悶,后來知道了,原來它是倒著放的。因?yàn)槭裁茨?#xff1f;因?yàn)镼uartz 2D坐標(biāo)系和UIKit的相反,所以會造成這種情況。
先不管反正了。反正畫了一個(gè)圖片到view上。看看代碼。應(yīng)該不用過多介紹了。CGContextDrawImage和剛才的CGContextDrawPath類似,只不過畫的東西不一樣罷了。里面要說下CGImageRef:它是一個(gè)結(jié)構(gòu)體:封裝了位圖圖像的信息。而UIImaged的CGImage就是返回的這樣的實(shí)例。其他不說了。
8、2D圖形基本變換:
有平移變換、縮放變換、旋轉(zhuǎn)變換、x軸對稱變換、y軸對稱變換、坐標(biāo)原點(diǎn)對稱變換。具體的都不詳細(xì)介紹了。應(yīng)該都能理解那些變換的意思。
9、CTM變換矩陣
不要看著CTM幾個(gè)字母就害怕,其實(shí)它就是current transformation matrix的簡稱。就是當(dāng)前矩陣變換。Quartz 2D提供了多種形式的變換,其中主要是CTM和仿射(Affine)變換。看一下CTM吧。
CTM主要涉及的函數(shù)有:
CGContextRotateCTM:旋轉(zhuǎn)變換
CGContextScaleCTM:縮放變換
CGContextTranslateCTM:平移變換
舉個(gè)簡單栗子:
- (void)tanslateImage {CGContextRef context = UIGraphicsGetCurrentContext();CGContextSaveGState(context);UIImage *image = [UIImage imageNamed:@"test"];CGImageRef cgImage = image.CGImage; // CGContextTranslateCTM(context, 0, image.size.height); // CGContextScaleCTM(context, -1, 1); CGContextTranslateCTM(context, 50, 50); //移動它的位置到100,50 // CGContextRotateCTM(context, 360);CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);CGContextDrawImage(context, rect, cgImage);CGContextRestoreGState(context); }看看結(jié)果:
使用了CGContextTranslateCTM,我們可以進(jìn)行位置調(diào)整。這里我把位置向右向下移動了50.就成這樣了。哪些旋轉(zhuǎn)和縮小就不說了,自己嘗試一把。
這里給出來代碼,可以試試:
/**旋轉(zhuǎn)變換*/#define radians(x) (x*M_PI/180)
- (void)rotateImage {CGContextRef context = UIGraphicsGetCurrentContext();CGContextSaveGState(context);UIImage *image = [UIImage imageNamed:@"test"];CGImageRef cgImage = image.CGImage;CGContextRotateCTM(context, radians(-45.));CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);CGContextDrawImage(context, rect, cgImage);CGContextRestoreGState(context); } /**縮小變換*/ - (void)scaleImage {CGContextRef context = UIGraphicsGetCurrentContext();CGContextSaveGState(context);UIImage *image = [UIImage imageNamed:@"test"];CGImageRef cgImage = image.CGImage;CGContextScaleCTM(context, .2, .40); //設(shè)置縮小大小CGRect rect = CGRectMake(0, image.size.height, image.size.width, image.size.height);CGContextDrawImage(context, rect, cgImage); }最后再給出一個(gè)比較厲害的讓你的圖片旋轉(zhuǎn)過來的方法:
//正向image - (void)drawNormalImage {CGContextRef context = UIGraphicsGetCurrentContext();CGContextSaveGState(context); //保留初始上下文UIImage *image = [UIImage imageNamed:@"test"];CGImageRef cgImage = image.CGImage;CGContextTranslateCTM(context, 0, image.size.height); //先做平移變換CGContextScaleCTM(context, 1, -1); //縮放變換x不變,y相反CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);CGContextDrawImage(context, rect, cgImage);CGContextRestoreGState(context); //還原初始上下文 // CGContextScaleCTM(context, -1, 1); // CGContextDrawImage(context, rect, cgImage); }其實(shí)讓圖片正過來很簡單,先做了平移變換,然后又縮放了一把,就0k了。
------------------------------------------------看累了嗎?繼續(xù)看。馬上完--------------------------------
仿射變換(Affine)
也是一種2D變換,他可以重用變換,經(jīng)過多次變換,每一種變換都可以用矩陣表示,通過多次矩陣相乘得到最后結(jié)果。(矩陣太難了。。。。。。。。。沒關(guān)系,理解就行了)
下面是一些訪射變換函數(shù):
CGAffineMakeRotation:創(chuàng)建新的旋轉(zhuǎn)變換矩陣
CGAffineMakeScale:創(chuàng)建新的 縮放矩陣函數(shù)
CGAffineMakeTranslation:創(chuàng)建新的平移矩陣
CGAffineTransformRotate:旋轉(zhuǎn)矩陣
CGAffineTransformScale:縮放矩陣
CGAffineTransformTranslate:平移矩陣
CGContextConcatCTM:連接到CTM變換。
這么多函數(shù)。這么多函數(shù)。這么多函數(shù)。太難了。。。。。。不過沒事。看看下面的例子你應(yīng)該就可以理解了。
- (void)normalImageByAffine {UIImage *image = [UIImage imageNamed:@"test"];CGImageRef cgImage = image.CGImage;CGContextRef context = UIGraphicsGetCurrentContext();CGContextSaveGState(context);CGAffineTransform myAffine = CGAffineTransformMakeTranslation(0, image.size.height);myAffine = CGAffineTransformScale(myAffine, 1, -1);CGContextConcatCTM(context, myAffine);CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);CGContextDrawImage(context, rect, cgImage);CGContextRestoreGState(context); }這個(gè)方法是通過仿射變換把剛剛倒過來的圖形放正。可以看一下:
CGAFffineTransform就是一個(gè)結(jié)構(gòu)體,可以用來接收CGAffineTransformMakeTranslate創(chuàng)建的仿射(平移)矩陣。
然后又CGAffineTransformScale:通過里面的參數(shù)來設(shè)置縮放矩陣.然后用CGContextConcatCTM連接到CTM變換。這樣就實(shí)現(xiàn)了圖像的正過來。drawNormalImage方法實(shí)現(xiàn)的效果是一樣的。
----------------------------------------------------這里是結(jié)束----------------------------------------------------
沒有了,這里就是結(jié)束了。
給個(gè)代碼把?好的好的。下面就是源碼:寫的比較亂,能看懂就行了。
http://pan.baidu.com/s/1kTMUyX5
謝謝百度網(wǎng)盤給的空間。
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的Quartz 2d绘图的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Sublime3安装过程及常用插件安装及
- 下一篇: python解释器内建函数002