iOS开发——图形编程OC篇&(六)Quartz 2D高级使用(二)

Quartz 2D高级使用

一、绘图路径

A.简单说明
在画线的时候,方法的内部默认创建一个path。它把路径都放到了path里面去。
1.创建路径  cgmutablepathref 调用该方法相当于创建了一个路径,这个路径用来保存绘图信息。
2.把绘图信息添加到路径里边。
以前的方法是点的位置添加到ctx(图形上下文信息)中,ctx 默认会在内部创建一个path用来保存绘图信息。
在图形上下文中有一块存储空间专门用来存储绘图信息,其实这块空间就是CGMutablePathRef。
3.把路径添加到上下文中。
代码示例:
绘制一条直线的代码:
技术分享
1     //1.获取图形上下文
2     CGContextRef ctx=UIGraphicsGetCurrentContext();
3     //2.绘图(画线)
4     //设置起点
5     CGContextMoveToPoint(ctx, 20, 20);
6     //设置终点
7     CGContextAddLineToPoint(ctx, 200, 300);
8     //渲染
9     CGContextStrokePath(ctx);
技术分享

上面的代码和下面的代码是等价的。

技术分享
 1     //1.获取图形上下文
 2     CGContextRef ctx=UIGraphicsGetCurrentContext();
 3     
 4     //2.绘图
 5     //2.1创建一条直线绘图的路径
 6     //注意:但凡通过Quartz2D中带有creat/copy/retain方法创建出来的值都必须要释放
 7     CGMutablePathRef path=CGPathCreateMutable();
 8     //2.2把绘图信息添加到路径里
 9     CGPathMoveToPoint(path, NULL, 20, 20);
10     CGPathAddLineToPoint(path, NULL, 200, 300);
11     //2.3把路径添加到上下文中
12     //把绘制直线的绘图信息保存到图形上下文中
13     CGContextAddPath(ctx, path);
14     
15     //3.渲染
16     CGContextStrokePath(ctx);
17     
18     //4.释放前面创建的两条路径
19     //第一种方法
20     CGPathRelease(path);
21     //第二种方法
22     //    CFRelease(path);
23 }
技术分享
 
B.直接使用path的好处:
第一种代码的阅读性不好,不便于区分。使用path,则一个path就代表一条路径。
比如:如果要在上下文中绘制多个图形,这种情况下建议使用path。
代码示例:
技术分享
 1 - (void)drawRect:(CGRect)rect
 2 {
 3     //1.获取图形上下文
 4     CGContextRef ctx=UIGraphicsGetCurrentContext();
 5 
 6     //2.绘图
 7     //2.a 画一条直线
 8     //2.a.1创建一条绘图的路径
 9     //注意:但凡通过Quartz2D中带有creat/copy/retain方法创建出来的值都必须要释放
10     CGMutablePathRef path=CGPathCreateMutable();
11     
12     //2.a.2把绘图信息添加到路径里
13     CGPathMoveToPoint(path, NULL, 20, 20);
14     CGPathAddLineToPoint(path, NULL, 200, 300);
15     
16     //2.a.3把路径添加到上下文中
17     //把绘制直线的绘图信息保存到图形上下文中
18     CGContextAddPath(ctx, path);
19     
20     
21     //2.b画一个圆
22     //2.b.1创建一条画圆的绘图路径(注意这里是可变的,不是CGPathRef)
23     CGMutablePathRef path1=CGPathCreateMutable();
24     
25     //2.b.2把圆的绘图信息添加到路径里
26     CGPathAddEllipseInRect(path1, NULL, CGRectMake(50, 50, 100, 100));
27     
28     //2.b.3把圆的路径添加到图形上下文中
29     CGContextAddPath(ctx, path1);
30     
31     
32     //3.渲染
33     CGContextStrokePath(ctx);
34     
35     //4.释放前面创建的两条路径
36     //第一种方法
37     CGPathRelease(path);
38     CGPathRelease(path1);
39     //第二种方法
40 //    CFRelease(path);
41 }
技术分享
效果:
技术分享
提示:如果是画线,那么就创建一条路径(path)用来保存画线的绘图信息,如果又要重新画一个圆,那么就可以创建一条新的路径来专门保存画圆的绘图信息。
注意:
但凡通过quarzt2d中带有creat/copy/retain方法创建出来的值都必须手动的释放
有两种方法可以释放前面创建的路径:
(1)CGPathRelease(path);
(2)CFRelease(path);
说明:CFRelease属于更底层的cocafoundation框架
 
二、补充知识点:
画四边形的一些方法:
第一种方式:通过连接固定的点绘制四边形
第二种方式:指定起点和宽高绘制四边形
第三种方式:把第二种方式中的两步合并成一步。
第四种方式(oc的方法):绘制实心的四边形,注意没有空心的方法
第五种:画根线,设置线条的宽度(通过这种方式可以画斜的四边形)
代码示例:
技术分享
 1 //
 2 //  YYview.m
 3 //  06-四边形的五种画法
 4 //
 5 //  Created by apple on 14-6-11.
 6 //  Copyright (c) 2014年 itcase. All rights reserved.
 7 //
 8 
 9 #import "YYview.h"
10 
11 @implementation YYview
12 
13 
14 - (void)drawRect:(CGRect)rect
15 {
16     //获取图形上下文
17     CGContextRef ctx=UIGraphicsGetCurrentContext();
18     //第一种画法,通过连接固定的点绘制四边形
19 //    CGContextMoveToPoint(ctx, 0, 20);
20 //    CGContextAddLineToPoint(<#CGContextRef c#>, <#CGFloat x#>, <#CGFloat y#>);
21 //    CGContextAddLineToPoint(<#CGContextRef c#>, <#CGFloat x#>, <#CGFloat y#>);
22 //    CGContextAddLineToPoint(<#CGContextRef c#>, <#CGFloat x#>, <#CGFloat y#>);
23     
24     //第二种方式:指定起点和宽高绘制四边形
25 //    CGContextAddRect(ctx, CGRectMake(20, 20, 200, 100));
26 //    //渲染
27 //    CGContextStrokePath(ctx);
28     
29     //第三种方式:二种的两步合并成一步。
30     //画空心的四边形
31 //    CGContextStrokeRect(ctx, CGRectMake(20, 20, 200, 100));
32 //    //画实心的四边形
33 //    CGContextFillRect(ctx, CGRectMake(20, 20, 200, 100));
34     
35     //第四种方式(oc的方法):绘制实心的四边形,注意没有空心的方法
36     UIRectFill(CGRectMake(20, 20, 200, 100));
37     
38     //第五种方式:画根线,设置线条的宽度(通过这种方式可以画斜的四边形)
39 //    CGContextMoveToPoint(ctx, 20, 20);
40 //    CGContextAddLineToPoint(ctx, 100, 200);
41 //    CGContextSetLineWidth(ctx, 50);
42 //    //注意,线条只能画成是空心的
43 //    CGContextStrokePath(ctx);
44     
45 }
46 @end
技术分享

第五种方法可以画斜的四边形。

技术分享

三、前导程序

新建一个项目,在主控制器文件中实现以下几行代码,就能轻松的完成图片在视图中的平铺。

技术分享
 1 #import "YYViewController.h"
 2 
 3 @interface YYViewController ()
 4 
 5 @end
 6 
 7 @implementation YYViewController
 8 
 9 - (void)viewDidLoad
10 {
11     [super viewDidLoad];
12 
13     UIImage *image=[UIImage imageNamed:@"me"];
14     UIColor *color=[UIColor colorWithPatternImage:image];
15     self.view.backgroundColor=color;
16 }
17 
18 @end
技术分享

效果:

技术分享

 

四、实现信纸条纹的效果

利用上面的这种特性来做一个信纸的效果。
默认的view上没有分割线,要在view上加上分割线有两种方式:
(1)让美工做一张专门用来做背景的图片,把图片设置为背景。缺点:信的长度不确定,所以背景图片的长度也难以确定。
(2)通过一张小的图片来创建一个颜色,平铺实现背景效果。
 
第一步:生成一张以后用以平铺的小图片。
画矩形。
画线条。
第二步:从上下文中取出图片设置为背景。黑乎乎一片?(其他地方时透明的,控制器的颜色,如果不设置那么默认为黑色的)
实现代码:
技术分享
 1 //
 2 //  YYViewController.m
 3 //  01-信纸条纹
 4 //
 5 //  Created by 孔医己 on 14-6-11.
 6 //  Copyright (c) 2014年 itcast. All rights reserved.
 7 //
 8 
 9 #import "YYViewController.h"
10 
11 @interface YYViewController ()
12 
13 @end
14 
15 @implementation YYViewController
16 
17 - (void)viewDidLoad
18 {
19     [super viewDidLoad];
20 
21     
22     // 1.生成一张以后用于平铺的小图片
23     CGSize size = CGSizeMake(self.view.frame.size.width, 35);
24     UIGraphicsBeginImageContextWithOptions(size , NO, 0);
25     
26     // 2.画矩形
27     CGContextRef ctx = UIGraphicsGetCurrentContext();
28     CGFloat height = 35;
29     CGContextAddRect(ctx, CGRectMake(0, 0, self.view.frame.size.width, height));
30     [[UIColor whiteColor] set];
31     CGContextFillPath(ctx);
32     
33     // 3.画线条
34     
35     CGFloat lineWidth = 2;
36     CGFloat lineY = height - lineWidth;
37     CGFloat lineX = 0;
38     CGContextMoveToPoint(ctx, lineX, lineY);
39     CGContextAddLineToPoint(ctx, 320, lineY);
40     [[UIColor blackColor] set];
41     CGContextStrokePath(ctx);
42     
43     
44     UIImage *image=UIGraphicsGetImageFromCurrentImageContext();
45     UIColor *color=[UIColor colorWithPatternImage:image];
46     self.view.backgroundColor=color;
47 }
48 
49 @end
技术分享

效果:

技术分享

五、应用场景

完成一个简陋的电子书阅读器

代码:

技术分享
 1 //
 2 //  YYViewController.m
 3 //  01-信纸条纹
 4 //
 5 //  Created by 孔医己 on 14-6-11.
 6 //  Copyright (c) 2014年 itcast. All rights reserved.
 7 //
 8 
 9 #import "YYViewController.h"
10 
11 @interface YYViewController ()
12 
13 @property (weak, nonatomic) IBOutlet UITextView *textview;
14 - (IBAction)perBtnClick:(UIButton *)sender;
15 - (IBAction)nextBtnClick:(UIButton *)sender;
16 @property(nonatomic,assign)int index;
17 @end
18 
19 @implementation YYViewController
20 
21 - (void)viewDidLoad
22 {
23     [super viewDidLoad];
24 
25     
26     // 1.生成一张以后用于平铺的小图片
27     CGSize size = CGSizeMake(self.view.frame.size.width, 26);
28     UIGraphicsBeginImageContextWithOptions(size , NO, 0);
29     
30     // 2.画矩形
31     CGContextRef ctx = UIGraphicsGetCurrentContext();
32     CGFloat height = 26;
33     CGContextAddRect(ctx, CGRectMake(0, 0, self.view.frame.size.width, height));
34     [[UIColor brownColor] set];
35     CGContextFillPath(ctx);
36     
37     // 3.画线条
38     
39     CGFloat lineWidth = 2;
40     CGFloat lineY = height - lineWidth;
41     CGFloat lineX = 0;
42     CGContextMoveToPoint(ctx, lineX, lineY);
43     CGContextAddLineToPoint(ctx, 320, lineY);
44     [[UIColor blackColor] set];
45     CGContextStrokePath(ctx);
46     
47     
48     UIImage *image=UIGraphicsGetImageFromCurrentImageContext();
49     UIColor *color=[UIColor colorWithPatternImage:image];
50     //self.view.backgroundColor=color;
51     self.textview.backgroundColor=color;
52 }
53 
54 - (IBAction)perBtnClick:(UIButton *)sender {
55     self.index--;
56     self.textview.text=[NSString stringWithFormat:@"第%d页",self.index];
57     CATransition *ca = [[CATransition alloc] init];
58     ca.type = @"pageCurl";
59     
60     [self.textview.layer addAnimation:ca forKey:nil];
61     
62 }
63 
64 - (IBAction)nextBtnClick:(UIButton *)sender {
65     self.index++;
66     self.textview.text=[NSString stringWithFormat:@"第%d页",self.index];
67     CATransition *ca = [[CATransition alloc] init];
68     ca.type = @"pageCurl";
69     
70     [self.textview.layer addAnimation:ca forKey:nil];
71 }
72 @end
技术分享

storyboard中的界面布局

技术分享

实现的简单效果:

技术分享       技术分享

 

六、简单说明(截屏)

在程序开发中,有时候需要截取屏幕上的某一块内容,比如捕鱼达人游戏。如图:

 技术分享

完成截屏功能的核心代码:- (void)renderInContext:(CGContextRef)ctx;调用某个view的layer的renderInContext:方法即可

七、代码示例

  storyboard界面搭建:

技术分享

代码:

技术分享
 1 //
 2 //  YYViewController.m
 3 //  01-截屏
 4 //
 5 //  Created by apple on 14-6-12.
 6 //  Copyright (c) 2014年 itcase. All rights reserved.
 7 //
 8 
 9 #import "YYViewController.h"
10 #import "MBProgressHUD+NJ.h"
11 
12 @interface YYViewController ()
13 @property (weak, nonatomic) IBOutlet UIView *contentView;
14 - (IBAction)BtnClick:(UIButton *)sender;
15 
16 @end
17 
18 @implementation YYViewController
19 
20 - (void)viewDidLoad
21 {
22     [super viewDidLoad];
23 }
24 
25 - (IBAction)BtnClick:(UIButton *)sender {
26     
27     //延迟两秒保存
28     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
29         //获取图形上下文
30         //    UIGraphicsBeginImageContext(self.view.frame.size);
31         UIGraphicsBeginImageContext(self.contentView.frame.size);
32         //将view绘制到图形上下文中
33         
34         //    [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
35         [self.contentView.layer renderInContext:UIGraphicsGetCurrentContext()];
36      
37         
38         //将截屏保存到相册
39         UIImage *newImage=UIGraphicsGetImageFromCurrentImageContext();
40         
41         UIImageWriteToSavedPhotosAlbum(newImage,self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
42     });
43 }
44 
45  - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
46 {
47     if (error) {
48         [MBProgressHUD showError:@"保存失败,请检查是否拥有相关的权限"];
49     }else
50     {
51 //        [MBProgressHUD showMessage:@"保存成功!"];
52         [MBProgressHUD showSuccess:@"保存成功!"];
53     }
54 }
55 
56 @end
技术分享
把截取的图片保存到手机的相册中:
技术分享
说明:把整个屏幕画到一张图片里
1.创建一个bitmap的上下文
2.将屏幕绘制带上下文中
3.从上下文中取出绘制好的图片
4.保存图片到相册 
补充:把图片写入到文件的代码
技术分享
1 //3.从上下文中取出绘制好的图片
2      UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
3      
4      NSData *data = UIImagePNGRepresentation(newImage);
5      
6      NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"abc.png"];
7      NSLog(@"%@", path);
8      [data writeToFile:path atomically:YES];
技术分享
八、补充
保存成功和保存失败之后应该做些事情?
系统推荐的方法:
技术分享
 1  - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
 2 {
 3     if (error) {
 4         [MBProgressHUD showError:@"保存失败,请检查是否拥有相关的权限"];
 5     }else
 6     {
 7 //        [MBProgressHUD showMessage:@"保存成功!"];
 8         [MBProgressHUD showSuccess:@"保存成功!"];
 9     }
10 }
技术分享
如果图片成功保存的话,那么就提示保存成功。
如果保存失败,那么提示失败
提示:保存失败常见有两个原因:1是内存不够,2是手机内部的权限不允许。
说明:如果当一个应用程序想要访问通讯录或相册,用户已经明确拒绝过,那么以后再要访问的话会直接拒绝。这个时候,可以提示用户去开启权限。
 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。