当前位置: 移动技术网 > IT编程>移动开发>IOS > IOS实现的简单画板功能

IOS实现的简单画板功能

2019年07月24日  | 移动技术网IT编程  | 我要评论

天道圣人之星辰天尊,创意居家,车载gps导航仪

效果图

设计要求

 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

到这里就差不多了,这个小功能实现的基本思路与具体代码我都已经放上来了,大家如果还有哪里不清楚的可以留言喔~~

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持移动技术网!

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网