和上一篇手势解锁不一样,手势解锁只画了一条路径,从触摸开始--》触摸移动--》触摸结束 ,然后路径完成了,渲染出来就是手势解锁了;

这次涂鸦想做到的效果是可以画很多次线段或弧,每次又可以设置不同的宽度和颜色,然后还要有撤销、清屏、橡皮擦的功能,那就需要画很多条路径了,然后每条路径有自己的颜色和宽度,那么

UIBezierPath类也实现不了,需要自定义一个类,继承自UIBezierPath,然后再增加自己的颜色和宽度属性。

效果截图:

  涂鸦了   橡皮擦擦除 

保存到相册

代码:

1、自定义PaintingBezierPath类继承自UIBezierPath类,增加一个自定义路径颜色的属性;自定义构造函数,设置颜色和路径宽度

PaintingBezierPath.h文件代码:

#import <UIKit/UIKit.h>

@interface PaintingBezierPath : UIBezierPath

@property (nonatomic, retain) UIColor *color; //线段的颜色

- (instancetype)initWithColor: (UIColor *)color WithWidth: (CGFloat)width WithStartPoint: (CGPoint)startPoint;

@end

PaintingBezierPath.m文件代码:

 //
// PaintingBezierPath.m
// tan_iosTwo
//
// Created by xiaom on 15/7/22.
//
// 为了自定义每个轨迹的宽度和颜色,需要增加一个自定义方法 #import "PaintingBezierPath.h" @implementation PaintingBezierPath - (instancetype)initWithColor:(UIColor *)color WithWidth:(CGFloat)width WithStartPoint:(CGPoint)startPoint{
if (self = [super init]){
self.color = color;
self.lineWidth = width;
self.lineJoinStyle = kCGLineJoinRound;
self.lineCapStyle = kCGLineCapRound;
[self moveToPoint:startPoint];
}
return self;
} @end

2、自定义view, 用来展示涂鸦,名称为:PaintingView

PaintingView.h文件代码:

#import <UIKit/UIKit.h>

@interface PaintingView : UIView

@property (nonatomic, assign) CGFloat lineWidth; //涂鸦的线段宽度
@property (nonatomic, strong) UIColor *lineColor; //涂鸦的线段颜色 - (void)cancelPainting; //撤销涂鸦
- (void)clearScreen; //清屏
- (void)saveImgToAlbum; //保存相片到到手机相册里 @end

PaintingView.m文件代码:

 //  绘画, 涂鸦

 #import "PaintingView.h"
#import "PaintingBezierPath.h" @interface PaintingView() @property (nonatomic, retain) NSMutableArray *paths; //涂鸦路径数组
@property (nonatomic, retain) PaintingBezierPath *currentPath; //当前正在绘制的path @end @implementation PaintingView //代码创建对象会调用: 使用
- (instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]){
//NSLog(@"frame...%s", __func__);
}
return self;
} //xib创建会调用
- (instancetype)initWithCoder:(NSCoder *)aDecoder{
if (self = [super initWithCoder:aDecoder]){
//NSLog(@"coder.. %s", __func__);
}
return self;
} //监听触摸开始 ,方法继承自UIResponder
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
PaintingBezierPath *path = [[PaintingBezierPath alloc] initWithColor:self.lineColor WithWidth:self.lineWidth WithStartPoint:[self currentPoint:touches]]; [self.paths addObject:path]; //将路径记录到数组中
self.currentPath = path; [self setNeedsDisplay]; //调用方法,重新绘制
} //监听触摸移动中
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
//追踪每次路径的移动过程
[self.currentPath addLineToPoint:[self currentPoint:touches]]; [self setNeedsDisplay]; //调用方法,重新绘制
} //获取view对象中的当前位置
- (CGPoint)currentPoint: (NSSet *)touches{
UITouch *touch = [touches anyObject];
return [touch locationInView:self];
} //次方法是UIView的分类@interface UIView(UIViewRendering)中添加的方法
//setNeedsDisplay方法也是此分类中的方法
- (void)drawRect:(CGRect)rect{
for (int i = ; i < self.paths.count; i++) {
PaintingBezierPath *path = [self.paths objectAtIndex:i];
[path.color set];
[path stroke]; //渲染
}
} #pragma mark - 自定义方法实现
//撤销
- (void)cancelPainting{
[self.paths removeLastObject]; //移除最后一个路径对象
[self setNeedsDisplay]; //重新绘制
} //清屏
- (void)clearScreen{
[self.paths removeAllObjects]; //移除所有路径
self.lineColor = nil; //颜色赋空
[self setNeedsDisplay]; //重新绘制
} //保存图片到相册
- (void)saveImgToAlbum{
//1、开启图形上下文
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);
//2、获取当前上下文
CGContextRef ctr = UIGraphicsGetCurrentContext();
//3、渲染当前View的图层到上下文中
[self.layer renderInContext:ctr];
//4、获取新图片
UIImage *newImg = UIGraphicsGetImageFromCurrentImageContext();
//5、关闭图形上下文
UIGraphicsEndImageContext();
//6、保存图片到相册中
UIImageWriteToSavedPhotosAlbum(newImg, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
} //保存图片到相册完成之后的处理
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(, , , )];
[lbl setBackgroundColor:[UIColor blackColor]];
lbl.textAlignment = NSTextAlignmentCenter;
lbl.textColor = [UIColor yellowColor]; if (error){ //保存失败
lbl.text = @"保存失败";
}
else{ //保存成功
lbl.text = @"保存成功";
}
[self addSubview:lbl]; [UIView animateWithDuration:2.0 animations:^{
lbl.alpha = 0.1;
} completion:^(BOOL finished) {
[lbl removeFromSuperview];
}];
} //设置对象默认属性值
- (CGFloat)lineWidth{
if (_lineWidth < ){
_lineWidth = ;
}
return _lineWidth;
} - (UIColor *)lineColor{
if (_lineColor == nil){
_lineColor = [UIColor blackColor];
}
return _lineColor;
} - (NSMutableArray *)paths{
if (_paths == nil){
_paths = [[NSMutableArray alloc] init];
}
return _paths;
} /*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/ @end

3、自定义控制器展示PaintingView

DoodleViewController.h文件:

#import <UIKit/UIKit.h>

@interface DoodleViewController : UIViewController

@end

DoodleViewController.m

 //  信手涂鸦

 #import "DoodleViewController.h"
#import "PaintingView.h" @interface DoodleViewController () @property (nonatomic, retain) PaintingView *paintV; //涂鸦的画板 @end @implementation DoodleViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.view setBackgroundColor:[UIColor whiteColor]]; //自定义View涂鸦
PaintingView *v = [[PaintingView alloc] initWithFrame:CGRectMake(, , , )];
[v setBackgroundColor:[UIColor grayColor]];
[v setAlpha:0.6];
[self.view addSubview:v];
self.paintV = v; [self addReturnBtn]; //添加返回按钮
[self addDoodleSetWidthAndColor]; //增加设置涂鸦的宽度和颜色设置
} //添加返回按钮
- (void)addReturnBtn{
UIButton *returnBtn = [[UIButton alloc] initWithFrame:CGRectMake(, , , )];
[returnBtn setTitle:@"返回" forState:UIControlStateNormal];
[returnBtn addTarget:self action:@selector(returnPrePage) forControlEvents:UIControlEventTouchUpInside];
[returnBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[self.view addSubview:returnBtn];
} //添加涂鸦宽度设置和颜色设置
- (void)addDoodleSetWidthAndColor{
//1、增加UISlider用来设置可调节宽度
UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(, , , )];
slider.maximumValue = 15.0f; //最大值
slider.value = 3.0f; //默认为1
self.paintV.lineWidth = slider.value;
[slider addTarget:self action:@selector(setLineWidth:) forControlEvents:UIControlEventValueChanged]; //绑定值改变事件
[self.view addSubview:slider]; //2、添加颜色选择按钮
NSArray *colors = @[[UIColor redColor], [UIColor yellowColor], [UIColor greenColor], [UIColor blueColor], [UIColor purpleColor], [UIColor brownColor]];
for (int i = ; i < colors.count; i++) {
CGFloat x = + * i;
UIButton *colorBtn = [[UIButton alloc] initWithFrame:CGRectMake(x, , , )];
[colorBtn setBackgroundColor:[colors objectAtIndex:i]];
[colorBtn addTarget:self action:@selector(setLineColor:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:colorBtn];
} //第二行
//3、添加撤销按钮
UIButton *cancelBtn = [[UIButton alloc] initWithFrame:CGRectMake(, , , )];
[cancelBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[cancelBtn setTitle:@"撤销" forState:UIControlStateNormal];
[cancelBtn addTarget:self action:@selector(cancelPainting) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:cancelBtn]; //4、清屏按钮
UIButton *clearScreenBtn = [[UIButton alloc] initWithFrame:CGRectMake(, , , )];
[clearScreenBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[clearScreenBtn setTitle:@"清屏" forState:UIControlStateNormal];
[clearScreenBtn addTarget:self action:@selector(clearScreen) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:clearScreenBtn]; //5、添加一个橡皮擦
UIButton *brushBtn = [[UIButton alloc] initWithFrame:CGRectMake(, , , )];
[brushBtn setTitle:@"橡皮擦" forState:UIControlStateNormal];
[brushBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[brushBtn addTarget:self action:@selector(brush) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:brushBtn]; //6、保存到相册按钮
UIButton *saveBtn = [[UIButton alloc] initWithFrame:CGRectMake(, , , )];
[saveBtn setTitle:@"保存到相册" forState:UIControlStateNormal];
[saveBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[saveBtn addTarget:self action:@selector(saveImgToAlbum) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:saveBtn];
} //调节宽度
- (void)setLineWidth:(UISlider *)sender{
[self.paintV setLineWidth:sender.value];
} //调节颜色
- (void)setLineColor: (UIButton *)sender{
[self.paintV setLineColor:sender.backgroundColor];
} //设置橡皮擦
- (void)brush{
self.paintV.lineColor = self.paintV.backgroundColor;
if (self.paintV.lineWidth < ) self.paintV.lineWidth = ;
}
//撤销
- (void)cancelPainting{
[self.paintV cancelPainting];
}
//清屏
- (void)clearScreen{
[self.paintV clearScreen];
} //保存图片到相册
- (void)saveImgToAlbum{
[self.paintV saveImgToAlbum];
} //返回上一页
- (void)returnPrePage{
[self dismissViewControllerAnimated:YES completion:nil];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} /*
#pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/ @end

Quartz2D复习(三) --- 涂鸦的更多相关文章

  1. Quartz2D复习(一)--- 基础知识 / 绘制线段圆弧 / 图片水印 / 截图

    1.Quartz 2D是一个二维绘图引擎,同时支持ios和Mac系统: Quart2D的API是纯C语言的,API来自于Core  Graphics框架: 2.Quartz 2D可以绘制图形(线段/三 ...

  2. C#复习三(Day 22)

    哈哈,又到了总结的时间了.今天还是在继续复习C#的基础语法.这次总结主要以一下小程序为主. Split()的运用 123-456---789-----123-2把类似的字符串中重复符号去掉,得到123 ...

  3. SQL复习三(子查询)

    子查询 子查询就是嵌套查询,即select中包含这select,如果一条语句中存在着两个,或者两个以上的select,那么就是子查询语句了. 子查询出现的位置 where后,作为条件的一部分: fro ...

  4. Linux 复习三

    第三章Linux使用进阶 一.磁盘管理和文件系统 1.磁盘的基本概念:磁头(head).柱面(cylinder).扇区(sector) Linux系统中所有的设备被抽象成文件,存储在/dev目录下 设 ...

  5. C# 基础复习 三 XML操作

    XML 可扩展标记语言(所有标签都是自己定义,没有固定格式) 如果要给XML规定格式,可以使用dtd (dtd是什么?你不会自己百度吗) XML主要用来存储数据 XML的要求:     根节点只能有一 ...

  6. 记录一次Quartz2D学习(三)

    在(二)内,讲到了几何图形的绘制,这次就讲文本与图片的绘制 3 图片与文本 3.1 文本绘制 - (void)drawRect:(CGRect)rect { NSString * str = @&qu ...

  7. Quartz2D复习(四) --- 图层CALayer和动画CAAnimation

    1.CALayer 1).在ios中,能看得见摸得着的东西基本上都是UIView, 比如按钮.文本标签.文本输入框.图标等,这些都是UIView 2).UIView之所以能显示在屏幕上,完全是因为它内 ...

  8. Quartz2D复习(二) --- 手势解锁

    这次支付宝手机客户端升级,把手势解锁那个功能去掉了,引起很多人的抱怨,觉得少了手势解锁的保护,个人信息容易泄漏了... 那么手势解锁功能是怎么是实现的呢,这里使用Quart2D来简单模拟一下, 先看下 ...

  9. java IO复习(三)

    package com.zyw.io; import java.io.File; import java.io.FilenameFilter; import java.util.ArrayList; ...

随机推荐

  1. Java学习笔记之使用反射+泛型构建通用DAO

    PS:最近简单的学了学后台Servlet+JSP.也就只能学到这里了.没那么多精力去学SSH了,毕竟Android还有很多东西都没学完.. 学习内容: 1.如何使用反射+泛型构建通用DAO. 1.使用 ...

  2. Azure China (12) 域名备案问题

    <Windows Azure Platform 系列文章目录> (1) 默认情况下,我们在创建的Azure 服务,默认使用的DNS地址为: http://xxx.chinacloudapi ...

  3. git代码回滚:Reset、Checkout、Revert的选择

    代码回滚:Reset.Checkout.Revert的选择 Zhongyi Tong edited this page on Dec 8, 2015 · 5 revisions Pages 19 Ho ...

  4. 在Visual Studio 2015 Preview 中使用Github 版本控制

    打开Visual Studio,新建项目,右下角勾选,如下图: 点击‘OK’后,出现下图窗口,选择'Git' : 如果是现有项目可以在‘文件’菜单下找到‘Add to Source Control’ ...

  5. 数据结构(C语言第2版)----时间复杂度和单链表

    马上要到校招了,复习下相关的基础知识. 时间复杂度是什么? 官方解释: 算法的执行时间需要依据算法所编制的程序在计算机上于运行时所消耗的时间来度量.在算法中可以使用基本的语句的执行次数作为算法的时间复 ...

  6. 对于一些Http远程连接Api安全的看法;

    文章来源于 :http://lesg.cn/?p=122 我的个人博客站点 对于一些Http远程连接Api安全的看法: 当不同系统需要互相通信的时候:如果无法用webservice等方式链接的时候另一 ...

  7. ASP.NET MVC 网站开发总结(七)——C#操作图片:多张图的拼接(旋转)

    其实用C#来操作图片的拼接就是在用Graphic画图.个人感觉还是挺有趣的,各种类库提供了丰富多彩的功能. 源代码(移植到一个简单的C#程序中,并没有放在ASP.NET项目中): using Syst ...

  8. 通过泛型数据,操作SQL数据库

    本人在操作数据库的时候,采用将对象的形式操作传入数据库,经过大量百度和朋友帮助,总结出如下两个接口.用于插入数据,提取数据. 要这样操作的前提条件,就是类名和表名一致,类字段和表字段一致就可以了 // ...

  9. jquery基本选择器id

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. 孙鑫MFC学习笔记4:MFC画图

    1.画线方法 *1.捕获鼠标按下和弹起消息,获取两个点 *2.消息响应,画线 2.在CMainFrame类中的鼠标左键事件得不到响应的原因是CNameView覆盖了CMainFrame 3.注释宏 4 ...