A.需求
1.超简易画图,只有一种画笔
2.清屏功能
3.回退功能
4.保存功能
5.使用了cocos2D
code source: https://github.com/hellovoidworld/PaintDemo
B.实现方法1
1.基本界面
(1)3个按钮:清屏、回退、保存
(2)绘图view

2.画线
(1)使用数组存储绘图点:存储一条线的数组、存储所有线的总数组
(2)在touch的开始、拖曳、结束记录触摸位置,触发重绘
3.清屏
删除总数组
4.回退
删除最后画的一条线:删除相应数组
5.保存到相册
使用”截图”功能,保存绘图view
1 //
2 // PaintView.m
3 // PaintDemo
4 //
5 // Created by hellovoidworld on 15/1/10.
6 // Copyright (c) 2015年 hellovoidworld. All rights reserved.
7 //
8
9 #import "PaintView.h"
10 #import "UIImage+Extension.h"
11
12 @interface PaintView()
13
14 @end
15
16 @implementation PaintView
17
18 - (NSMutableArray *)lines {
19 if (nil == _lines) {
20 _lines = [NSMutableArray array];
21 }
22 return _lines;
23 }
24
25 #PRagma mark - 触摸事件
26 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
27 UITouch *touch = [touches anyObject];
28 CGPoint startLocation = [touch locationInView:touch.view];
29
30 // 开启一条新的线
31 NSMutableArray *points = [NSMutableArray array];
32 // 存储点信息到线上
33 [points addObject:[NSValue valueWithCGPoint:startLocation]];
34 // 存储到线组上
35 [self.lines addObject:points];
36
37 // 重绘
38 [self setNeedsDisplay];
39 }
40
41 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
42 UITouch *touch = [touches anyObject];
43 CGPoint location = [touch locationInView:touch.view];
44
45 // 拿到正在画的线
46 NSMutableArray *points = [self.lines lastObject];
47 // 添加点信息
48 [points addObject:[NSValue valueWithCGPoint:location]];
49
50 // 重绘
51 [self setNeedsDisplay];
52 }
53
54 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
55 // 停止拖曳的逻辑其实和拖曳中是一样的
56 [self touchesMoved:touches withEvent:event];
57 }
58
59 #pragma mark - 绘图方法
60 /** 绘图 */
61 - (void)drawRect:(CGRect)rect {
62 CGContextRef ctx = UIGraphicsGetCurrentContext();
63
64 // 遍历线组,把所有线画出来
65 for (NSArray *line in self.lines) {
66 for (int i=0; i<line.count; i++) {
67 NSValue *pointValue = line[i];
68 CGPoint point = [pointValue CGPointValue];
69
70 // 如果是线的第一个点,要先移动画笔到那个点
71 if (0 == i) {
72 CGContextMoveToPoint(ctx, point.x, point.y);
73 } else {
74 CGContextAddLineToPoint(ctx, point.x, point.y);
75 }
76 }
77 }
78
79 // 设置线宽、线头样式、线转折样式
80 CGContextSetLineWidth(ctx, 5);
81 CGContextSetLineCap(ctx, kCGLineCapRound);
82 CGContextSetLineJoin(ctx, kCGLineJoinRound);
83
84 // 渲染
85 CGContextStrokePath(ctx);
86 }
87
88 #pragma mark - view操作方法
89 /** 回退 */
90 - (void)rollback {
91 [self.lines removeLastObject];
92 [self setNeedsDisplay];
93 }
94
95 /** 清屏 */
96 - (void)clearScreen {
97 [self.lines removeAllObjects];
98 [self setNeedsDisplay];
99 }
100
101 /** 保存 */
102 - (void)save {
103 // 1.获取图片
104 UIImage *image = [UIImage imageOfView:self];
105
106 // 2.保存图片到相册
107 UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
108 }
109
110 /** 保存图片后激发事件
111 * 这是文档推荐的方法
112 */
113 - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
114 if (error) {
115 NSLog(@"保存失败");
116 } else {
117 NSLog(@"保存成功");
118 }
119 }
120
121 @end
1 //
2 // UIImage+Extension.m
3 // PaintDemo
4 //
5 // Created by hellovoidworld on 15/1/11.
6 // Copyright (c) 2015年 hellovoidworld. All rights reserved.
7 //
8
9 #import "UIImage+Extension.h"
10
11 @implementation UIImage(Extension)
12
13 + (UIImage *) imageOfView:(UIView *) view {
14 // 1.开启图片上下文
15 UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, 0.0);
16
17 // 2.将view的layer渲染到上下文
18 [view.layer renderInContext:UIGraphicsGetCurrentContext()];
19
20 // 3.获取上下文中的图片
21 UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
22
23 // 4.关闭图片上下文
24 UIGraphicsEndImageContext();
25
26 return image;
27 }
28
29 @end
C.实现方法2
1.基本界面和方法1一样
2.画线
(1)使用贝塞尔路径UIBezierPath,一条线就是一个UIBezierPath对象
(2)同样使用数组来存储UIBezierPath对象
3.清屏、回退、保存和方法1一样
1 //
2 // BezierPaintView.m
3 // PaintDemo
4 //
5 // Created by hellovoidworld on 15/1/11.
6 // Copyright (c) 2015年 hellovoidworld. All rights reserved.
7 //
8
9 #import "BezierPaintView.h"
10 #import "UIImage+Extension.h"
11
12 @implementation BezierPaintView
13
14 - (NSMutableArray *)lines {
15 if (nil == _lines) {
16 _lines = [NSMutableArray array];
17 }
18 return _lines;
19 }
20
21 #pragma mark - 触摸事件
22 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
23 UITouch *touch = [touches anyObject];
24 CGPoint startLocation = [touch locationInView:touch.view];
25
26 // 新建一条Bezier线
27 UIBezierPath *path = [UIBezierPath bezierPath];
28 [path setLineWidth:5.0];
29 [path setLineCapStyle:kCGLineCapRound];
30 [path setLineJoinStyle:kCGLineJoinRound];
31
32 // 移动到始点
33 [path moveToPoint:startLocation];
34 // 添加Bezier线到数组
35 [self.lines addObject:path];
36
37 // 重绘
38 [self setNeedsDisplay];
39 }
40
41 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
42 UITouch *touch = [touches anyObject];
43 CGPoint location = [touch locationInView:touch.view];
44
45 // 获得正在画的线
46 UIBezierPath *path = [self.lines lastObject];
47 // 画线-添加点信息
48 [path addLineToPoint:location];
49
50 // 重绘
51 [self setNeedsDisplay];
52 }
53
54 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
55 // 停止拖曳的逻辑其实和拖曳中是一样的
56 [self touchesMoved:touches withEvent:event];
57 }
58
59 #pragma mark - 绘图方法
60 /** 绘图 */
61 - (void)drawRect:(CGRect)rect {
62
63 // 画出所有的线
64 for (UIBezierPath *path in self.lines) {
65 // 渲染
66 [path stroke];
67 }
68
69 }
70
71 #pragma mark - view操作方法
72 /** 回退 */
73 - (void)rollback {
74 [self.lines removeLastObject];
75 [self setNeedsDisplay];
76 }
77
78 /** 清屏 */
79 - (void)clearScreen {
80 [self.lines removeAllObjects];
81 [self setNeedsDisplay];
82 }
83
84 /** 保存 */
85 - (void)save {
86 // 1.获取图片
87 UIImage *image = [UIImage imageOfView:self];
88
89 // 2.保存图片到相册
90 UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
91 }
92
93 /** 保存图片后激发事件
94 * 这是文档推荐的方法
95 */
96 - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
97 if (error) {
98 NSLog(@"保存失败");
99 } else {
100 NSLog(@"保存成功");
101 }
102 }
103
104 @end
D.附加功能

1.slider调整线宽
(1)使用slider控件
(2)通过slider的valueChange事件调用方法设置线宽
2.选择颜色
(1)创建一个“色块”类
- 使用UIView作为色块
- 自定义一个继承UIView的类,作为色块class,给色块UIView加上点击事件
- 给色块UIView创建一个颜色属性和代理协议,代理是ViewController;创建一个点击代理事件方法
1 //
2 // ColorSelectionView.h
3 // PaintDemo
4 //
5 // Created by hellovoidworld on 15/1/11.
6 // Copyright (c) 2015年 hellovoidworld. All rights reserved.
7 //
8
9 #import <UIKit/UIKit.h>
10
11 @protocol ColorSelectionViewDelegate <NSObject>
12
13 /** “色块”点击代理方法 */
14 @optional
15 - (void) selectColor:(UIColor *) selectedColor;
16
17 @end
18
19 @interface ColorSelectionView : UIView
20
21 /** 代理 */
22 @property(nonatomic, strong) id<ColorSelectionViewDelegate> delegate;
23
24 @end
25
26 //
27 // ColorSelectionView.m
28 // PaintDemo
29 //
30 // Created by hellovoidworld on 15/1/11.
31 // Copyright (c) 2015年 hellovoidworld. All rights reserved.
32 //
33
34 #import "ColorSelectionView.h"
35
36 @implementation ColorSelectionView
37
38 - (void)awakeFromNib {
39 // 给UIView设置点击事件
40 UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(colorClicked)];
41 [self addGestureRecognizer:tapGesture];
42 }
43
44 /** “色块”点击事件 */
45 - (void) colorClicked {
46 [self.delegate selectColor:self.backgroundColor];
47 }
48
49 @end
(2)自定义一个继承UIBezierPath的类,增加一个线颜色的属性
1 //
2 // HVWBezierPath.h
3 // PaintDemo
4 //
5 // Created by hellovoidworld on 15/1/11.
6 // Copyright (c) 2015年 hellovoidworld. All rights reserved.
7 //
8
9 #import <UIKit/UIKit.h>
10
11 @interface HVWBezierPath : UIBezierPath
12
13 /** 颜色 */
14 @property(nonatomic, strong) UIColor *color;
15
16 @end
(3)ViewController代理“色块”的点击事件
- 拖入所有“色块”对象到ViewController,设置代理
- 遵守“色块”协议,实现代理方法
1 //
2 // ViewController.m
3 // PaintDemo
4 //
5 // Created by hellovoidworld on 15/1/10.
6 // Copyright (c) 2015年 hellovoidworld. All rights reserved.
7 //
8
9 #import "ViewController.h"
10 #import "BezierPaintView.h"
11 #import "ColorSelectionView.h"
12
13 @interface ViewController () <ColorSelectionViewDelegate>
14
15 @property (weak, nonatomic) IBOutlet BezierPaintView *paintView;
16
17 /** 颜色选择集合 */
18 @property (strong, nonatomic) IBOutletCollection(ColorSelectionView) NSArray *colorSelection;
19
20 - (IBAction)rollback;
21 - (IBAction)clearScreen;
22 - (IBAction)save;
23 - (IBAction)lineWidthChange:(UISlider *)sender;
24
25 @end
26
27 @implementation ViewController
28
29 - (void)viewDidLoad {
30 [super viewDidLoad];
31 // Do any additional setup after loading the view, typically from a nib.
32
33 // 设置颜色选择器的代理
34 for (ColorSelectionView *colorView in self.colorSelection) {
35 colorView.delegate = self;
36 }
37 }
38
39 - (void)didReceiveMemoryWarning {
40 [super didReceiveMemoryWarning];
41 // Dispose of any resources that can be recreated.
42 }
43
44 /** 回退 */
45 - (IBAction)rollback {
46 [self.paintView rollback];
47 }
48
49 /** 清屏 */
50 - (IBAction)clearScreen {
51 [self.paintView clearScreen];
52 }
53
54 /** 保存 */
55 - (IBAction)save {
56 [self.paintView save];
57 }
58
59 /** 改变线粗 */
60 - (IBAction)lineWidthChange:(UISlider *)sender {
61 self.paintView.lineWidth = sender.value;
62 }
63
64 #pragma mark - ColorSelectionViewDelegate 代理方法
65 - (void) selectColor:(UIColor *) selectedColor {
66 self.paintView.lineColor = selectedColor;
67 }
@end
(4)“画板”在开始画一条线的时候(触摸开始),设置线宽和颜色
1 //
2 // BezierPaintView.m
3 // PaintDemo
4 //
5 // Created by hellovoidworld on 15/1/11.
6 // Copyright (c) 2015年 hellovoidworld. All rights reserved.
7 //
8
9 #import "BezierPaintView.h"
10 #import "UIImage+Extension.h"
11 #import "HVWBezierPath.h"
12
13 @interface BezierPaintView()
14
15 @end
16
17 @implementation BezierPaintView
18
19 - (NSMutableArray *)lines {
20 if (nil == _lines) {
21 _lines = [NSMutableArray array];
22 }
23 return _lines;
24 }
25
26 #pragma mark - 触摸事件
27 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
28 UITouch *touch = [touches anyObject];
29 CGPoint startLocation = [touch locationInView:touch.view];
30
31 // 新建一条Bezier线
32 HVWBezierPath *path = [[HVWBezierPath alloc] init];
33
34 // 配置线粗
35 if (self.lineWidth) {
36 [path setLineWidth:self.lineWidth];
37 }
38
39 // 配置线色
40 if (self.lineColor) {
41 path.color = self.lineColor;
42 }
43
44 [path setLineCapStyle:kCGLineCapRound];
45 [path setLineJoinStyle:kCGLineJoinRound];
46
47 // 移动到始点
48 [path moveToPoint:startLocation];
49 // 添加Bezier线到数组
50 [self.lines addObject:path];
51
52 // 重绘
53 [self setNeedsDisplay];
54 }
55
56 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
57 UITouch *touch = [touches anyObject];
58 CGPoint location = [touch locationInView:touch.view];
59
60 // 获得正在画的线
61 HVWBezierPath *path = [self.lines lastObject];
62 // 画线-添加点信息
63 [path addLineToPoint:location];
64
65 // 重绘
66 [self setNeedsDisplay];
67 }
68
69 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
70 // 停止拖曳的逻辑其实和拖曳中是一样的
71 [self touchesMoved:touches withEvent:event];
72 }
73
74 #pragma mark - 绘图方法
75 /** 绘图 */
76 - (void)drawRect:(CGRect)rect {
77
78 // 画出所有的线
79 for (HVWBezierPath *path in self.lines) {
80
81 // 设置颜色
82 if (path.color) {
83 [path.color set];
84 }
85
86 // 渲染
87 [path stroke];
88 }
89
90 }
91
92 #pragma mark - view操作方法
93 /** 回退 */
94 - (void)rollback {
95 [self.lines removeLastObject];
96 [self setNeedsDisplay];
97 }
98
99 /** 清屏 */
100 - (void)clearScreen {
101 [self.lines removeAllObjects];
102 [self setNeedsDisplay];
103 }
104
105 /** 保存 */
106 - (void)save {
107 // 1.获取图片
108 UIImage *image = [UIImage imageOfView:self];
109
110 // 2.保存图片到相册
111 UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
112 }
113
114 /** 保存图片后激发事件
115 * 这是文档推荐的方法
116 */
117 - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
118 if (error) {
119 NSLog(@"保存失败");
120 } else {
121 NSLog(@"保存成功");
122 }
123 }
124
125
126 @end