IOS实现的简单画板功能
效果图
设计要求
1、画笔能设置大小、颜色
2、有清屏、撤销、橡皮擦、导入照片功能
3、能将绘好的画面保存到相册
实现思路
1、画笔的实现,我们可以通过监听用户的 平移手势 中创建 uibezierpath 来实现线条的绘制
2、撤销功能,我们先来看下撤销功能,我们会想到用一个数组队列将用户的每一次的笔画都加入到数组中,然后撤销的时候只需要将最后添加进去的笔画pop掉,重新绘制就可以了
3、清屏功能就简单了,只需要将上面说到的那个数组清空重新绘制下就可以了
4、导入照片功能,可以用系统的 uiimagepickercontroller 选取照片得到uiimage,然后再将 uiimage 绘制到屏幕中就可以了
5、保存到相册功能,可以使用 uigraphicsgetimagefromcurrentimagecontext 获取当前的图片上下文,得到屏幕画面的 uiimage ,然后通过 uiimagewritetosavedphotosalbum 写入到相册
具体代码实现
1、先画个界面
2、因为我们绘制线条会用到 uibezierpath ,并且要能可设置颜色,但是uibezierpath是没有设置颜色的属性,所以我们这里需要简单扩展一下,创建一个继承于 uibezierpath 的子类 drawpath
// // drawpath.h // 画板 // // created by xgao on 16/4/13. // copyright © 2016年 xgao. all rights reserved. // #import <uikit/uikit.h> @interface drawpath : uibezierpath // 画笔颜色 @property(nonatomic,retain)uicolor* pathcolor; @end
这个子类只需要扩展一个属性,就是 pathcolor 用来保存画笔的颜色
// // drawpath.m // 画板 // // created by xgao on 16/4/13. // copyright © 2016年 xgao. all rights reserved. // #import "drawpath.h" @implementation drawpath @end
drawpath.m 里面不需要做其它功能
3、接到来我们对画板功能的实现封装一下,创建一个继承于uiview的 drawview子类
// // drawview.h // 画板 // // created by xgao on 16/4/13. // copyright © 2016年 xgao. all rights reserved. // #import <uikit/uikit.h> @interface drawview : uiview // 画线的宽度 @property(nonatomic,assign)cgfloat linewidth; // 线条颜色 @property(nonatomic,retain)uicolor* pathcolor; // 加载背景图片 @property(nonatomic,strong)uiimage* image; // 清屏 - (void)clear; // 撤销 - (void)undo; // 橡皮擦 - (void)eraser; // 保存 - (void)save; @end
// // drawview.m // 画板 // // created by xgao on 16/4/13. // copyright © 2016年 xgao. all rights reserved. // #import "drawview.h" #import "drawpath.h" @interface drawview() @property(nonatomic,strong) drawpath* path; // 线的数组 @property(nonatomic,strong) nsmutablearray* paths; @end @implementation drawview - (void)awakefromnib{ [self setup]; } - (instancetype)initwithframe:(cgrect)frame { self = [super initwithframe:frame]; if (self) { [self setup]; } return self; } // 重绘ui - (void)drawrect:(cgrect)rect { for (drawpath* path in self.paths) { if ([path iskindofclass:[uiimage class]]) { // 画图片 uiimage* image = (uiimage*)path; [image drawinrect:rect]; }else{ // 画线 // 设置画笔颜色 [path.pathcolor set]; // 绘制 [path stroke]; } } } // 懒加载属性 - (nsmutablearray*)paths{ if (_paths == nil) { _paths = [nsmutablearray array]; } return _paths; } // 重写image属性 - (void)setimage:(uiimage *)image{ _image = image; // 将图片加入到线条数组中 [self.paths addobject:image]; [self setneedsdisplay]; } #pragma mark - init // 初始化 - (void)setup{ // 添加平移手势 uipangesturerecognizer* panges = [[uipangesturerecognizer alloc]initwithtarget:self action:@selector(panges:)]; [self addgesturerecognizer:panges]; // 默认值 self.linewidth = 1; self.pathcolor = [uicolor blackcolor]; } #pragma mark - event // 平移事件 - (void)panges:(uipangesturerecognizer*)ges{ // 获取当前点 cgpoint curpoint = [ges locationinview:self]; if (ges.state == uigesturerecognizerstatebegan) { // 开始移动 // 创建贝塞尔曲线 _path = [[drawpath alloc]init]; // 设置线条宽度 _path.linewidth = _linewidth; // 线条默认颜色 _path.pathcolor = _pathcolor; // 设置起始点 [_path movetopoint:curpoint]; [self.paths addobject:_path]; } // 连线 [_path addlinetopoint:curpoint]; // 重绘 [self setneedsdisplay]; } #pragma mark - method // 清屏 - (void)clear{ [self.paths removeallobjects]; [self setneedsdisplay]; } // 撤销 - (void)undo{ [self.paths removelastobject]; [self setneedsdisplay]; } // 橡皮擦 - (void)eraser{ self.pathcolor = [uicolor whitecolor]; [self setneedsdisplay]; } // 保存 - (void)save{ // ---- 截图操作 // 开启上下文 uigraphicsbeginimagecontextwithoptions(self.frame.size, no, 0); // 获取当前上下文 cgcontextref context = uigraphicsgetcurrentcontext(); // 渲染图层到上下文 [self.layer renderincontext:context]; // 从上下文中获取图片 uiimage* image = uigraphicsgetimagefromcurrentimagecontext(); // 关闭上下文 uigraphicsendimagecontext(); // ---- 保存图片 uiimagewritetosavedphotosalbum(image, self, @selector(image:didfinishsavingwitherror:contextinfo:), nil); } // 图片保存方法,必需写这个方法体,不能会保存不了图片 - (void)image:(uiimage *)image didfinishsavingwitherror:(nserror *)error contextinfo:(void *)contextinfo{ // 提示 uialertview* alert = [[uialertview alloc]initwithtitle:@"保存成功" message:nil delegate:nil cancelbuttontitle:@"ok" otherbuttontitles:nil, nil]; [alert show]; } @end
4、接下来就是如果使用这个画板类了,直接上代码吧
// // viewcontroller.m // 画板 // // created by xgao on 16/4/13. // copyright © 2016年 xgao. all rights reserved. // #import "viewcontroller.h" #import "drawview.h" @interface viewcontroller ()<uiimagepickercontrollerdelegate,uinavigationcontrollerdelegate> // 画板 @property (weak, nonatomic) iboutlet drawview *drawview; @end @implementation viewcontroller - (void)viewdidload { [super viewdidload]; } #pragma mark - event // 线条宽度变化 - (ibaction)linewidthchange:(uislider*)sender { _drawview.linewidth = sender.value; } // 线条颜色变化 - (ibaction)pathcolorchange:(uibutton*)sender { _drawview.pathcolor = sender.backgroundcolor; } // 清屏 - (ibaction)clearaction:(id)sender { [_drawview clear]; } // 撤销 - (ibaction)undoaction:(id)sender { [_drawview undo]; } // 橡皮擦 - (ibaction)eraseraction:(id)sender { [_drawview eraser]; } // 照片 - (ibaction)pickerphotoaction:(id)sender { // 照片选择控制器 uiimagepickercontroller* picvc = [[uiimagepickercontroller alloc]init]; // 照片源 picvc.sourcetype = uiimagepickercontrollersourcetypephotolibrary; // 委托 picvc.delegate = self; [self presentviewcontroller:picvc animated:yes completion:nil]; } // 保存 - (ibaction)saveaction:(id)sender { [_drawview save]; } #pragma mark - uiimagepickercontrollerdelegate - (void)imagepickercontroller:(uiimagepickercontroller *)picker didfinishpickingimage:(uiimage *)image editinginfo:(nullable nsdictionary<nsstring *,id> *)editinginfo{ // 设置图片 _drawview.image = image; // 关闭窗口 [self dismissviewcontrolleranimated:yes completion:nil]; } @end
到这里就差不多了,这个小功能实现的基本思路与具体代码我都已经放上来了,大家如果还有哪里不清楚的可以留言喔~~
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!