需求:实现一个简易的涂鸦板应用,使用鼠标在涂鸦板内拖动即可进行涂鸦,点击保存按钮,可以把完成的涂鸦保存,点击回退按钮可以向后退回一步,点击清空可以让涂鸦板清空。
实现步骤:
1、布局storyboard,连线各按钮以及涂鸦板;
2、监听触摸事件,主要为touchesBegan:和touchesMoved:;
3、获取移动的路径并添加到 UIBezierPath 对象;
4、渲染;
示例文件结构:
具体实现代码:
1 // 2 // Scrawl.h 3 // 1-04-Scrawl 4 // 5 // Created by xiaomoge on 15/1/4. 6 // Copyright (c) 2015年 xiaomoge. All rights reserved. 7 // 8 9 #import <UIKit/UIKit.h> 10 11 @interface Scrawl : UIView 12 /* 13 涂鸦线条的宽度 14 */ 15 @property (nonatomic,assign) CGFloat linsWidth; 16 /* 17 回退 18 */ 19 - (void)back; 20 /* 21 清屏 22 */ 23 - (void)clear; 24 @end
1 // 2 // Scrawl.m 3 // 1-04-Scrawl 4 // 5 // Created by xiaomoge on 15/1/4. 6 // Copyright (c) 2015年 xiaomoge. All rights reserved. 7 // 8 9 #import "Scrawl.h" 10 @interface Scrawl () 11 /* 12 存储所有线的路径的数组 13 */ 14 @property (nonatomic,strong) NSMutableArray *linsPath; 15 @end 16 @implementation Scrawl 17 #pragma mark - 懒加载 18 - (NSMutableArray *)linsPath { 19 if (!_linsPath) { 20 _linsPath = [NSMutableArray array]; 21 } 22 return _linsPath; 23 } 24 - (void)drawRect:(CGRect)rect { 25 //获得当前数组中的总数 26 NSInteger count = self.linsPath.count; 27 for (NSInteger i = 0; i < count; i ++) { 28 //取得一个path对象 29 UIBezierPath *path = self.linsPath[i]; 30 //设置线宽 31 path.lineWidth = self.linsWidth; 32 //设置线的首尾样式 33 path.lineCapStyle = kCGLineCapRound; 34 //设置线的连接样式 35 path.lineJoinStyle = kCGLineJoinRound; 36 //渲染 37 [path stroke]; 38 } 39 } 40 //开始触摸事件 41 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 42 //取得当前触摸点的位置 43 UITouch *touch = [touches anyObject]; 44 CGPoint point = [touch locationInView:touch.view]; 45 //创建一个path对象,注意这里是[UIBezierPath bezierPath] 46 UIBezierPath *path = [UIBezierPath bezierPath]; 47 //创建path对象的起点位置 48 [path moveToPoint:point]; 49 //添加到线的路径数组中 50 [self.linsPath addObject:path]; 51 } 52 //移动触摸事件 53 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 54 //取得当前触摸点的位置 55 UITouch *touch = [touches anyObject]; 56 CGPoint point = [touch locationInView:touch.view]; 57 //创建一个path对象,为线的路径当前的点 58 UIBezierPath *path = [self.linsPath lastObject]; 59 //设置path对象的结束点 60 [path addLineToPoint:point]; 61 //重绘 62 [self setNeedsDisplay]; 63 } 64 //回退事件 65 - (void)back { 66 //回退其实就是把最后的一条线给清除 67 [self.linsPath removeLastObject]; 68 //然后重绘 69 [self setNeedsDisplay]; 70 } 71 - (void)clear { 72 //回退其实就是把所有的线给清除掉 73 [self.linsPath removeAllObjects]; 74 //然后重绘 75 [self setNeedsDisplay]; 76 } 77 @end
1 // 2 // ViewController.m 3 // 1-04-Scrawl 4 // 5 // Created by xiaomoge on 15/1/4. 6 // Copyright (c) 2015年 xiaomoge. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 #import "Scrawl.h" 11 @interface ViewController () 12 @property (weak, nonatomic) IBOutlet Scrawl *scrawlView; 13 14 @end 15 16 @implementation ViewController 17 18 - (void)viewDidLoad { 19 [super viewDidLoad]; 20 self.scrawlView.linsWidth = 3; 21 } 22 - (IBAction)backClick { 23 [self.scrawlView back]; 24 } 25 - (IBAction)clearClick { 26 [self.scrawlView clear]; 27 } 28 - (IBAction)saveClick { 29 //开启位图上下文 30 UIGraphicsBeginImageContext(self.scrawlView.frame.size); 31 //渲染 32 [self.scrawlView.layer renderInContext:UIGraphicsGetCurrentContext()]; 33 //获取当前位图上下文里的图片 34 UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); 35 //结束位图上下文的编辑 36 UIGraphicsEndImageContext(); 37 //把图片转为NSData 38 NSData *data = UIImagePNGRepresentation(img); 39 //保存 40 [data writeToFile:@"/Users/xiaobao/Desktop/scrawl.png" atomically:YES]; 41 //注意,这里其实也可以把这个保存图片抽取成一个方法,然后调用即可。 42 } 43 @end
最后的效果(点击保存按钮保存下来的整个涂鸦板):