iOS:quartz2D绘图小项目(涂鸦画板)
介绍:学了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绘图小项目(涂鸦画板)相关推荐
- iOS:quartz2D绘图 (动画)
quartz2D可以用来绘制自己需要的图形,它们绘制出来的是一个静态的图形,那么如何绘制一个动态的图形呢?动态的图形就是动画,所谓动画,其实就是很多张图片在短时间内不停的切换所产生的一种视觉效果.qu ...
- 小项目——涂鸦图片数据挖掘
在这里插入图片描述前言: 最近在玩涂鸦,打算多看看别人大神的作品,学习学习.为此决定去百度图片上爬一些下来,以供学习(嘿嘿) 上菜! 还是先分析源代码找正则,直接百度图片,涂鸦,查看源代码 发现有许多 ...
- iOS Quartz2D绘图使用篇
Quartz2D使用 有兴趣可以贴代码看一下跑的效果,就不一一上图了 文章目录 Quartz2D使用 常用的一些函数 栗子
- 制作一个有趣的涂鸦物联网小项目(涂鸦模组SDK开发 CBU BK7231N WiFi+蓝牙模组 HSV彩色控制)
实现的功能: l APP控制月球灯 l 本地月球灯控制 l APP控制"大白"颜色,实现各种颜色变身 l 门状态传感器状态APP显示 l 网络状态指示灯,连接服务器长亮, ...
- ios小项目——新浪微博客户端总结
2019独角兽企业重金招聘Python工程师标准>>> 们还是登录不了,你们要用还是得自己申请appkey并且把回调网址设为baidu.或者是再下面留言,留下你的微博uid我把你加入 ...
- 在线涂鸦画板小程序源码
简介: 一款功能简单的在线涂鸦画板小程序源码,可以二次开发 网盘下载地址: http://kekewangLuo.net/VsCTzCLAOVM0 图片:
- IOS-小项目(饿了么 网络部分 简单实现)
在介绍小项目之前,在此说明一下此代码并非本人所写,我只是随笔的整理者. 在介绍之前先展现一下效果图. 看过效果图大家应该很熟悉了,就是饿了么的一个界面而已,值得注意的是,实现时并没有采用本地连接,而是 ...
- iOS、mac开源项目及库
1.用来生成 @3x 的图片资源对应的 @2x 和 @1x 版本,只要拖拽高清图到 @3x 的位置上,然后按Ctrl+Shift+A即可自动生成两张低清的补全空位.当然你也可以从 @2x 的图生成 @ ...
- android 仿qq修改头像,Qt:小项目仿QQ修改头像界面,技术点记录
最近写了一个修改头像功能的UI,布局参考了QQ目前的修改头像界面.如下图 这里主要说明一下两个地方的技术:1.头像图片上层的遮罩层,圆形外部为灰色,内部为全透明:2.上传图片宽高比例可以通过鼠标拖拽移 ...
最新文章
- php 返回字符串给aja,解决ajax异步请求返回的是字符串问题
- 微盟“删库”程序员被判6年,供述无力偿还网贷,酒后感觉生活不如意
- System.img是如何打包的
- “花钱矩阵”下共享单车的出路何在?
- python3 生成器的send_Python:生成器中send()的行为
- SQLite B+树实现代码
- 切图崽的自我修养-规范CSS元素命名
- idea连接mysql怎么生成实体类_IDEA链接数据库自动生成实体类
- 刷题总结——树的同构(bzoj4337 树上hash)
- C语言---输出三角形字符阵列
- 跳转引用、禅模式...VS Code 中 11 个快捷键/操作,让你的效率与舒适度翻倍!
- linux vi 编辑命令
- 信息文档分工会在运动会象棋比赛中夺得佳绩
- 计算机应用与篮球有关的文章,浅析计算机技术应用对高校篮球教学的作用与影响...
- ucgui添加自定义汉字库
- [python][pandas]pandas数据处理+直方图绘制
- C++11 function类模板
- 英雄联盟——心得体会
- Python3批量修改图片像素
- codeforces水题100道 第九题 Codeforces Beta Round #63 (Div. 2) Young Physicist (math)