介绍:学了quartz2D的绘图知识后,我根据它的一些功能制作了一个小项目:涂鸦画板。

功能:绘制各种图形,还可以选取相册上的照片做涂鸦,然后保存到相册中。其中,还包括功能有:颜色的选取、线宽的选取、橡皮擦除、撤销上一次绘制痕迹、清除所有痕迹。

用到的自定义控件:工具栏控件(UIToolBar)、工具栏上的按钮控件(UIBarButtonItem)、警告框控件(UIAlertView、UIActionSheet)、图像选择器控制器控件(UIImagePickerController)等。

需要的类:除了应用程序代理类AppDelegate和控制器类ViewController外,还需要一个自定义的视图类DemoView和一个自定义的绘制路径类MyPath。MyPath类是用来封装绘制路径的,因为路径是结构体,所以不能直接动作对象使用,封装后可以将路径保存数组中,用来连续绘图。

具体操作如下:

1、创建如上介绍的类的截图为:

2、将自定义的视图类DemiView与控制器的视图关联起来:

   

3、下面就是具体针对每一个类的代码了:

<1>在MyPath.h文件中

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#define PHOTO_RECT (CGRectMake(0,0,375,667))//绘制照片局域宏定义
@interface MyPath : NSObject
@property (assign,nonatomic)CGMutablePathRef path;   //可变的路径
@property (strong,nonatomic)UIColor *color;  //颜色
@property (assign,nonatomic)NSInteger lineWidth; //线宽
@property (strong,nonatomic)UIImage *image;//图像
@end

<2>在Application.m文件中:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {//设置偏好NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];[userDefaults setBool:YES forKey:@"isDefualtColor"];[userDefaults setBool:YES forKey:@"isDefualtLine"];[userDefaults synchronize];return YES;
}

<3>在DemoView类中

DemoView.h文件

#import <UIKit/UIKit.h>
@interface DemoView : UIView
@property (strong,nonatomic)UIColor *color;        //颜色
@property (assign,nonatomic)NSInteger lineWidth;   //线宽
@property (strong,nonatomic)NSMutableArray *paths; //可变数组,用来保存路径
@property(assign,nonatomic)BOOL isUndo;  //标示符
@property (strong,nonatomic)UIImage *image; //图像
@property (assign,nonatomic)CGMutablePathRef path; //可变的路径
@end

DemoView.m文件

//懒加载

-(NSMutableArray*)paths
{if (!_paths){_paths = [NSMutableArray array];}return _paths;
}

//画图

- (void)drawRect:(CGRect)rect
{    //1.获取绘制图上下文CGContextRef context = UIGraphicsGetCurrentContext();//4.添加保存的路径到上下文for (MyPath *myPath in self.paths){CGContextAddPath(context, myPath.path);if(myPath.image){[myPath.image drawInRect:PHOTO_RECT];}//设置绘图属性[myPath.color set];CGContextSetLineWidth(context, myPath.lineWidth);//绘制路径
        CGContextDrawPath(context, kCGPathStroke);}//如果是清除或撤销,就不执行当前绘图if (!self.isUndo){if(self.image){[self.image drawInRect:PHOTO_RECT];}//添加当前路径
        CGContextAddPath(context, _path);//5.设置当前绘图属性[self.color set];CGContextSetLineWidth(context, self.lineWidth);//6.绘制路径
        CGContextDrawPath(context, kCGPathStroke);}
}

//开始触摸事件(设置绘制属性)

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{self.isUndo = NO;NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];    if ([userDefaults boolForKey:@"isDefualtColor"]){//设置默认颜色self.color = [UIColor blackColor];}if ([userDefaults boolForKey:@"isDefualtLine"]){//设置默认线宽self.lineWidth = 1.0;}//接收颜色通知[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(seclectColor:) name:@"ColorNitification" object:nil];//接收线宽通知[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(selectedWidth:) name:@"WidthNitification"  object:nil];//创建路径_path = CGPathCreateMutable();//创建起始点UITouch *touch = [touches anyObject];CGPoint location = [touch locationInView:self];CGPathMoveToPoint(_path, nil, location.x, location.y);
}

//获取通知中的颜色和线宽数据

//从通知中获取颜色
-(void)seclectColor:(NSNotification*)notification
{self.color = notification.object;if (self.color == NULL){self.color = [UIColor blackColor];}
}//从通知中获取线宽
-(void)selectedWidth:(NSNotification*) notification
{NSNumber *number = notification.object;self.lineWidth = [number integerValue];if (self.lineWidth == 0){self.lineWidth = 1.0;}
}

//触摸移动(添加新路径,刷新视图)

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{if (_path){//向路径添加新的直线UITouch *touch = [touches anyObject];CGPoint location = [touch locationInView:self];CGPathAddLineToPoint(_path, nil, location.x, location.y);//让视图刷新
        [self setNeedsDisplay];}
}

//触摸结束(封装路径并保存到数组中)

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{if (_path){//保存路径MyPath *myPath = [[MyPath alloc]init];myPath.path = self.path;myPath.color = self.color;myPath.lineWidth = self.lineWidth;if(self.image){myPath.image = self.image;self.image = nil;}//保存路径[self.paths addObject:myPath];}
}

//清理路径

-(void)dealloc
{//清理保存的路径for (MyPath *myPath in self.paths){CGPathRelease(myPath.path);}
}

<4>在ViewController.m文件中

//设置属性

@interface ViewController ()<UIAlertViewDelegate,UIActionSheetDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate>
@property (strong,nonatomic)UIToolbar *toolBar;
@property (strong,nonatomic)NSMutableDictionary *DicM;@end

//初始化和创建控件

- (void)viewDidLoad {[super viewDidLoad];//初始化self.DicM = [NSMutableDictionary dictionary];((DemoView *)self.view).isUndo = NO;//创建工具栏对象self.toolBar = [[UIToolbar alloc]init];self.toolBar.barTintColor = [UIColor brownColor];self.toolBar.frame = CGRectMake(0, 0, 375, 40);//创建工具栏项目UIBarButtonItem *colorItem = [[UIBarButtonItem alloc]initWithTitle:@"颜色" style:UIBarButtonItemStylePlain target:self action:@selector(SelectColor:)];UIBarButtonItem *lineWidthItem = [[UIBarButtonItem alloc]initWithTitle:@"线宽" style:UIBarButtonItemStylePlain target:self action:@selector(SelectWidth:)];UIBarButtonItem *clearpartItem = [[UIBarButtonItem alloc]initWithTitle:@"橡皮" style:UIBarButtonItemStylePlain target:self action:@selector(ClearPart:)];UIBarButtonItem *backdoneItem = [[UIBarButtonItem alloc]initWithTitle:@"撤销" style:UIBarButtonItemStylePlain target:self action:@selector(BackDone:)];UIBarButtonItem *clearallItem = [[UIBarButtonItem alloc]initWithTitle:@"清空" style:UIBarButtonItemStylePlain target:self action:@selector(ClearAll:)];UIBarButtonItem *photoItem = [[UIBarButtonItem alloc]initWithTitle:@"照片" style:UIBarButtonItemStylePlain target:self action:@selector(selectPhoto:)];UIBarButtonItem *saveItem = [[UIBarButtonItem alloc]initWithTitle:@"保存" style:UIBarButtonItemStylePlain target:self action:@selector(Save:)];UIBarButtonItem *flexibleItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];[self.toolBar setItems:@[colorItem,flexibleItem,lineWidthItem,flexibleItem,clearpartItem,flexibleItem,backdoneItem,flexibleItem,clearallItem,flexibleItem,photoItem,flexibleItem,saveItem]];[self.view addSubview:self.toolBar];  //开始时隐藏工具栏self.toolBar.hidden = YES;//创建点击手势(双击时显示和隐藏工具栏)UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(showToolBar:)];//设置点击次数tap.numberOfTapsRequired = 2;//添加手势
    [self.view addGestureRecognizer:tap];
}

//设置颜色选项

//选择颜色
-(void)SelectColor:(UIBarButtonItem *)sender
{UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:nil message:@"可选颜色" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"红色",@"绿色",@"紫色",@"黄色",@"黑色",@"白色",@"蓝色",@"灰色",@"棕色",nil];[self.DicM setObject:[UIColor redColor]   forKey:@"红色"];[self.DicM setObject:[UIColor greenColor] forKey:@"绿色"];[self.DicM setObject:[UIColor purpleColor]forKey:@"紫色"];[self.DicM setObject:[UIColor yellowColor]forKey:@"黄色"];[self.DicM setObject:[UIColor blackColor] forKey:@"黑色"];[self.DicM setObject:[UIColor whiteColor] forKey:@"白色"];[self.DicM setObject:[UIColor blueColor]  forKey:@"蓝色"];[self.DicM setObject:[UIColor grayColor]  forKey:@"灰色"];[self.DicM setObject:[UIColor brownColor] forKey:@"棕色"];[alertView show];
}

//设置线宽选项

//选择线宽
-(void)SelectWidth:(UIBarButtonItem *)sender
{UIActionSheet *actionSheet = [[UIActionSheet alloc]initWithTitle:@"可选线宽" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"1号",@"2号",@"3号",@"4号",@"5号",@"6号",@"7号",@"8号",@"9号",@"10号",nil];[self.DicM setObject:[NSNumber numberWithInteger:1]  forKey:@"1号"];[self.DicM setObject:[NSNumber numberWithInteger:2]  forKey:@"2号"];[self.DicM setObject:[NSNumber numberWithInteger:3]  forKey:@"3号"];[self.DicM setObject:[NSNumber numberWithInteger:4]  forKey:@"4号"];[self.DicM setObject:[NSNumber numberWithInteger:5]  forKey:@"5号"];[self.DicM setObject:[NSNumber numberWithInteger:6]  forKey:@"6号"];[self.DicM setObject:[NSNumber numberWithInteger:7]  forKey:@"7号"];[self.DicM setObject:[NSNumber numberWithInteger:8]  forKey:@"8号"];[self.DicM setObject:[NSNumber numberWithInteger:9]  forKey:@"9号"];[self.DicM setObject:[NSNumber numberWithInteger:10] forKey:@"10号"];[actionSheet showInView:self.view];
}

//实现UIAlertView警告框协议

#pragma mark -<UIAlertViewDelegate>
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{NSString *key = [alertView buttonTitleAtIndex:buttonIndex];UIColor *selectedcolor = [self.DicM objectForKey:key];//发送通知附带颜色数据[[NSNotificationCenter defaultCenter]postNotificationName:@"ColorNitification" object:selectedcolor];//重设偏好[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"isDefualtColor"];[[NSUserDefaults standardUserDefaults] synchronize];
}

//实现UIActionSheet警告框协议

#pragma mark -<UIActionSheetDelegate>
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{NSString *key = [actionSheet buttonTitleAtIndex:buttonIndex];NSNumber *number = [self.DicM objectForKey:key];//发送通知附带线宽数据[[NSNotificationCenter defaultCenter]postNotificationName:@"WidthNitification" object:number];//重设偏好[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"isDefualtLine"];[[NSUserDefaults standardUserDefaults] synchronize];
}

//擦除功能

//橡皮擦除(其实就是用白色重绘)
-(void)ClearPart:(UIBarButtonItem *)sender
{UIColor *selectedcolor = [UIColor whiteColor];[[NSNotificationCenter defaultCenter]postNotificationName:@"ColorNitification" object:selectedcolor];NSNumber *number = [NSNumber numberWithInteger:10];[[NSNotificationCenter defaultCenter]postNotificationName:@"WidthNitification" object:number];//重设偏好[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"isDefualtColor"];[[NSUserDefaults standardUserDefaults] synchronize];[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"isDefualtLine"];[[NSUserDefaults standardUserDefaults] synchronize];
}

//撤销功能

//撤销
-(void)BackDone:(UIBarButtonItem *)sender
{//先做清理工作MyPath *path = [((DemoView *)self.view).paths lastObject];CGPathRelease(path.path);//删除最后一个路径[((DemoView *)self.view).paths removeLastObject];((DemoView *)self.view).image = nil;((DemoView *)self.view).isUndo = YES;//让视图重绘
    [self.view setNeedsDisplay];
}

//清空功能

//清空绘图
-(void)ClearAll:(UIBarButtonItem *)sender
{//先做清理工作for(MyPath *path in ((DemoView *)self.view).paths){CGPathRelease(path.path);}//删除所有[((DemoView *)self.view).paths removeAllObjects];((DemoView *)self.view).image = nil;((DemoView *)self.view).isUndo = YES;//让视图重绘
    [self.view setNeedsDisplay];
}

//保存绘图功能

//保存绘图
-(void)Save:(UIBarButtonItem *)sender
{[self didSelectedSave];
}
-(void)didSelectedSave
{//开始图像绘制上下文
    UIGraphicsBeginImageContext(self.view.bounds.size);CGContextRef context = UIGraphicsGetCurrentContext();// 先画保存的pathfor(MyPath *myPath in ((DemoView *)self.view).paths){if(myPath.image){[myPath.image drawInRect: PHOTO_RECT ];}CGContextAddPath(context, myPath.path);[myPath.color set];CGContextSetLineWidth(context, myPath.lineWidth);CGContextStrokePath(context);}//获取绘制的图片UIImage *image = UIGraphicsGetImageFromCurrentImageContext();//结束图像绘制上下文
    UIGraphicsEndImageContext();//保存图片
    UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL);
}
- (void)image: (UIImage *) imagedidFinishSavingWithError: (NSError *) errorcontextInfo: (void *) contextInfo
{NSString *msg = nil;if(error){msg = @"图片保存失败";}else{msg = @"图片保存成功";}UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"保存图片" message:msg delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];[alert show];
}

//选取照片功能

//选取照片
-(void)selectPhoto:(UIBarButtonItem*)sender
{[self didSelectedPhoto];
}-(void)didSelectedPhoto
{//显示照片选择窗口UIImagePickerController *picker = [[UIImagePickerController alloc]init];//图片来源是相册picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;picker.delegate = self;//以模态窗口的形式显示图片
    [self presentViewController:picker animated:YES completion:nil];
}

//图像选择器控制器协议方法

#pragma mark - imagePikerController 代理方法
//选取图片
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{//取出图片UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];((DemoView *)self.view).image = image;((DemoView *)self.view).isUndo = NO;//创建路径((DemoView *)self.view).path = CGPathCreateMutable();//关闭模态窗口
    [picker dismissViewControllerAnimated:YES completion:nil];//刷新视图
    [self.view setNeedsDisplay];
}

//手势事件,是否显示工具栏

//按钮事件是否显示工具栏
-(void)showToolBar:(UIButton *)sender
{self.toolBar.hidden = !self.toolBar.hidden;
}

演示截图如下:

开始时:                                             双击显示工具栏:

    

(使用默认颜色和线宽)绘制直线                                            选颜色绘制直线 ,选红色

   

接着选择线宽绘制直线:选10号

  

点击橡皮擦除:                         点击撤销,被擦除部分还原

     

点击清空,什么都没有了:                                                 点击照片,打开相册

   

任意选取一张照片,选取X

  

绘制图片并保存到相册:

    

查看保存的图片

 

可以再双击隐藏工具栏:

iOS:quartz2D绘图小项目(涂鸦画板)相关推荐

  1. iOS:quartz2D绘图 (动画)

    quartz2D可以用来绘制自己需要的图形,它们绘制出来的是一个静态的图形,那么如何绘制一个动态的图形呢?动态的图形就是动画,所谓动画,其实就是很多张图片在短时间内不停的切换所产生的一种视觉效果.qu ...

  2. 小项目——涂鸦图片数据挖掘

    在这里插入图片描述前言: 最近在玩涂鸦,打算多看看别人大神的作品,学习学习.为此决定去百度图片上爬一些下来,以供学习(嘿嘿) 上菜! 还是先分析源代码找正则,直接百度图片,涂鸦,查看源代码 发现有许多 ...

  3. iOS Quartz2D绘图使用篇

    Quartz2D使用 有兴趣可以贴代码看一下跑的效果,就不一一上图了 文章目录 Quartz2D使用 常用的一些函数 栗子

  4. 制作一个有趣的涂鸦物联网小项目(涂鸦模组SDK开发 CBU BK7231N WiFi+蓝牙模组 HSV彩色控制)

    实现的功能: l  APP控制月球灯 l  本地月球灯控制 l  APP控制"大白"颜色,实现各种颜色变身 l  门状态传感器状态APP显示 l  网络状态指示灯,连接服务器长亮, ...

  5. ios小项目——新浪微博客户端总结

    2019独角兽企业重金招聘Python工程师标准>>> 们还是登录不了,你们要用还是得自己申请appkey并且把回调网址设为baidu.或者是再下面留言,留下你的微博uid我把你加入 ...

  6. 在线涂鸦画板小程序源码

    简介: 一款功能简单的在线涂鸦画板小程序源码,可以二次开发 网盘下载地址: http://kekewangLuo.net/VsCTzCLAOVM0 图片:

  7. IOS-小项目(饿了么 网络部分 简单实现)

    在介绍小项目之前,在此说明一下此代码并非本人所写,我只是随笔的整理者. 在介绍之前先展现一下效果图. 看过效果图大家应该很熟悉了,就是饿了么的一个界面而已,值得注意的是,实现时并没有采用本地连接,而是 ...

  8. iOS、mac开源项目及库

    1.用来生成 @3x 的图片资源对应的 @2x 和 @1x 版本,只要拖拽高清图到 @3x 的位置上,然后按Ctrl+Shift+A即可自动生成两张低清的补全空位.当然你也可以从 @2x 的图生成 @ ...

  9. android 仿qq修改头像,Qt:小项目仿QQ修改头像界面,技术点记录

    最近写了一个修改头像功能的UI,布局参考了QQ目前的修改头像界面.如下图 这里主要说明一下两个地方的技术:1.头像图片上层的遮罩层,圆形外部为灰色,内部为全透明:2.上传图片宽高比例可以通过鼠标拖拽移 ...

最新文章

  1. php 返回字符串给aja,解决ajax异步请求返回的是字符串问题
  2. 微盟“删库”程序员被判6年,供述无力偿还网贷,酒后感觉生活不如意
  3. System.img是如何打包的
  4. “花钱矩阵”下共享单车的出路何在?
  5. python3 生成器的send_Python:生成器中send()的行为
  6. SQLite B+树实现代码
  7. 切图崽的自我修养-规范CSS元素命名
  8. idea连接mysql怎么生成实体类_IDEA链接数据库自动生成实体类
  9. 刷题总结——树的同构(bzoj4337 树上hash)
  10. C语言---输出三角形字符阵列
  11. 跳转引用、禅模式...VS Code 中 11 个快捷键/操作,让你的效率与舒适度翻倍!
  12. linux vi 编辑命令
  13. 信息文档分工会在运动会象棋比赛中夺得佳绩
  14. 计算机应用与篮球有关的文章,浅析计算机技术应用对高校篮球教学的作用与影响...
  15. ucgui添加自定义汉字库
  16. [python][pandas]pandas数据处理+直方图绘制
  17. C++11 function类模板
  18. 英雄联盟——心得体会
  19. Python3批量修改图片像素
  20. codeforces水题100道 第九题 Codeforces Beta Round #63 (Div. 2) Young Physicist (math)

热门文章

  1. mysqldump只导出数据或者只导出表结构
  2. Product user profile information 没有导入
  3. 俄罗斯国家黑客TA505被指攻击金融机构
  4. 对开源库 limdu 命令注入漏洞 (CVE-2020-4066) 的简要分析
  5. 为避免攻击,研究员把严重的比特币漏洞详情焐了两年
  6. HR经常会用到的面试问题
  7. 4.8 定位一组元素
  8. python-可变循环
  9. [Spring实战系列](18)注解切面
  10. 排序算法系列之归并排序