博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
IOS简单画板实现
阅读量:7287 次
发布时间:2019-06-30

本文共 6229 字,大约阅读时间需要 20 分钟。

效果图

 

 

 设计要求

 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 
@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 
@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 ()
// 画板@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
*)editingInfo{ // 设置图片 _drawView.image = image; // 关闭窗口 [self dismissViewControllerAnimated:YES completion:nil];}@end

 

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

 

 

 

 

转载于:https://www.cnblogs.com/xgao/p/6650225.html

你可能感兴趣的文章
Angular CLI 创建你的第一个 Angular 示例程序
查看>>
关于error LNK2019: unresolved external symbol错误
查看>>
cacti+nagios 之cacti插件安装monitor和ntop(五)
查看>>
VIM
查看>>
bootstrap-table 设置宽度
查看>>
express学习小结
查看>>
Spring day01(3)
查看>>
浅析java内存模型--JMM
查看>>
DHCP动态主机配置协议
查看>>
Python教程 | Requests的基本用法
查看>>
AJPFX关于抽象方法和接口
查看>>
在eclipse中安装SVN插件方法
查看>>
js特效
查看>>
TCP/IP、Http、Socket的区别
查看>>
我的友情链接
查看>>
request.getParameterValues("ic")
查看>>
我的友情链接
查看>>
AJAX的post提交数组数据
查看>>
项目在eclipse运行正常,但单独部署到tomcat上出现乱码解决办法
查看>>
【数据库】转换成3NF的保持函数依赖的分解
查看>>