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

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

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

效果截图:

  涂鸦了   橡皮擦擦除 

保存到相册

代码:

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

PaintingBezierPath.h文件代码:

  1. #import <UIKit/UIKit.h>
  2.  
  3. @interface PaintingBezierPath : UIBezierPath
  4.  
  5. @property (nonatomic, retain) UIColor *color; //线段的颜色
  6.  
  7. - (instancetype)initWithColor: (UIColor *)color WithWidth: (CGFloat)width WithStartPoint: (CGPoint)startPoint;
  8.  
  9. @end

PaintingBezierPath.m文件代码:

  1. //
  2. // PaintingBezierPath.m
  3. // tan_iosTwo
  4. //
  5. // Created by xiaom on 15/7/22.
  6. //
  7. // 为了自定义每个轨迹的宽度和颜色,需要增加一个自定义方法
  8.  
  9. #import "PaintingBezierPath.h"
  10.  
  11. @implementation PaintingBezierPath
  12.  
  13. - (instancetype)initWithColor:(UIColor *)color WithWidth:(CGFloat)width WithStartPoint:(CGPoint)startPoint{
  14. if (self = [super init]){
  15. self.color = color;
  16. self.lineWidth = width;
  17. self.lineJoinStyle = kCGLineJoinRound;
  18. self.lineCapStyle = kCGLineCapRound;
  19. [self moveToPoint:startPoint];
  20. }
  21. return self;
  22. }
  23.  
  24. @end

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

PaintingView.h文件代码:

  1. #import <UIKit/UIKit.h>
  2.  
  3. @interface PaintingView : UIView
  4.  
  5. @property (nonatomic, assign) CGFloat lineWidth; //涂鸦的线段宽度
  6. @property (nonatomic, strong) UIColor *lineColor; //涂鸦的线段颜色
  7.  
  8. - (void)cancelPainting; //撤销涂鸦
  9. - (void)clearScreen; //清屏
  10. - (void)saveImgToAlbum; //保存相片到到手机相册里
  11.  
  12. @end

PaintingView.m文件代码:

  1. // 绘画, 涂鸦
  2.  
  3. #import "PaintingView.h"
  4. #import "PaintingBezierPath.h"
  5.  
  6. @interface PaintingView()
  7.  
  8. @property (nonatomic, retain) NSMutableArray *paths; //涂鸦路径数组
  9. @property (nonatomic, retain) PaintingBezierPath *currentPath; //当前正在绘制的path
  10.  
  11. @end
  12.  
  13. @implementation PaintingView
  14.  
  15. //代码创建对象会调用: 使用
  16. - (instancetype)initWithFrame:(CGRect)frame{
  17. if (self = [super initWithFrame:frame]){
  18. //NSLog(@"frame...%s", __func__);
  19. }
  20. return self;
  21. }
  22.  
  23. //xib创建会调用
  24. - (instancetype)initWithCoder:(NSCoder *)aDecoder{
  25. if (self = [super initWithCoder:aDecoder]){
  26. //NSLog(@"coder.. %s", __func__);
  27. }
  28. return self;
  29. }
  30.  
  31. //监听触摸开始 ,方法继承自UIResponder
  32. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
  33. PaintingBezierPath *path = [[PaintingBezierPath alloc] initWithColor:self.lineColor WithWidth:self.lineWidth WithStartPoint:[self currentPoint:touches]];
  34.  
  35. [self.paths addObject:path]; //将路径记录到数组中
  36. self.currentPath = path;
  37.  
  38. [self setNeedsDisplay]; //调用方法,重新绘制
  39. }
  40.  
  41. //监听触摸移动中
  42. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
  43. //追踪每次路径的移动过程
  44. [self.currentPath addLineToPoint:[self currentPoint:touches]];
  45.  
  46. [self setNeedsDisplay]; //调用方法,重新绘制
  47. }
  48.  
  49. //获取view对象中的当前位置
  50. - (CGPoint)currentPoint: (NSSet *)touches{
  51. UITouch *touch = [touches anyObject];
  52. return [touch locationInView:self];
  53. }
  54.  
  55. //次方法是UIView的分类@interface UIView(UIViewRendering)中添加的方法
  56. //setNeedsDisplay方法也是此分类中的方法
  57. - (void)drawRect:(CGRect)rect{
  58. for (int i = ; i < self.paths.count; i++) {
  59. PaintingBezierPath *path = [self.paths objectAtIndex:i];
  60. [path.color set];
  61. [path stroke]; //渲染
  62. }
  63. }
  64.  
  65. #pragma mark - 自定义方法实现
  66. //撤销
  67. - (void)cancelPainting{
  68. [self.paths removeLastObject]; //移除最后一个路径对象
  69. [self setNeedsDisplay]; //重新绘制
  70. }
  71.  
  72. //清屏
  73. - (void)clearScreen{
  74. [self.paths removeAllObjects]; //移除所有路径
  75. self.lineColor = nil; //颜色赋空
  76. [self setNeedsDisplay]; //重新绘制
  77. }
  78.  
  79. //保存图片到相册
  80. - (void)saveImgToAlbum{
  81. //1、开启图形上下文
  82. UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);
  83. //2、获取当前上下文
  84. CGContextRef ctr = UIGraphicsGetCurrentContext();
  85. //3、渲染当前View的图层到上下文中
  86. [self.layer renderInContext:ctr];
  87. //4、获取新图片
  88. UIImage *newImg = UIGraphicsGetImageFromCurrentImageContext();
  89. //5、关闭图形上下文
  90. UIGraphicsEndImageContext();
  91. //6、保存图片到相册中
  92. UIImageWriteToSavedPhotosAlbum(newImg, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
  93. }
  94.  
  95. //保存图片到相册完成之后的处理
  96. - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{
  97. UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(, , , )];
  98. [lbl setBackgroundColor:[UIColor blackColor]];
  99. lbl.textAlignment = NSTextAlignmentCenter;
  100. lbl.textColor = [UIColor yellowColor];
  101.  
  102. if (error){ //保存失败
  103. lbl.text = @"保存失败";
  104. }
  105. else{ //保存成功
  106. lbl.text = @"保存成功";
  107. }
  108. [self addSubview:lbl];
  109.  
  110. [UIView animateWithDuration:2.0 animations:^{
  111. lbl.alpha = 0.1;
  112. } completion:^(BOOL finished) {
  113. [lbl removeFromSuperview];
  114. }];
  115. }
  116.  
  117. //设置对象默认属性值
  118. - (CGFloat)lineWidth{
  119. if (_lineWidth < ){
  120. _lineWidth = ;
  121. }
  122. return _lineWidth;
  123. }
  124.  
  125. - (UIColor *)lineColor{
  126. if (_lineColor == nil){
  127. _lineColor = [UIColor blackColor];
  128. }
  129. return _lineColor;
  130. }
  131.  
  132. - (NSMutableArray *)paths{
  133. if (_paths == nil){
  134. _paths = [[NSMutableArray alloc] init];
  135. }
  136. return _paths;
  137. }
  138.  
  139. /*
  140. // Only override drawRect: if you perform custom drawing.
  141. // An empty implementation adversely affects performance during animation.
  142. - (void)drawRect:(CGRect)rect {
  143. // Drawing code
  144. }
  145. */
  146.  
  147. @end

3、自定义控制器展示PaintingView

DoodleViewController.h文件:

  1. #import <UIKit/UIKit.h>
  2.  
  3. @interface DoodleViewController : UIViewController
  4.  
  5. @end

DoodleViewController.m

  1. // 信手涂鸦
  2.  
  3. #import "DoodleViewController.h"
  4. #import "PaintingView.h"
  5.  
  6. @interface DoodleViewController ()
  7.  
  8. @property (nonatomic, retain) PaintingView *paintV; //涂鸦的画板
  9.  
  10. @end
  11.  
  12. @implementation DoodleViewController
  13.  
  14. - (void)viewDidLoad {
  15. [super viewDidLoad];
  16. // Do any additional setup after loading the view.
  17. [self.view setBackgroundColor:[UIColor whiteColor]];
  18.  
  19. //自定义View涂鸦
  20. PaintingView *v = [[PaintingView alloc] initWithFrame:CGRectMake(, , , )];
  21. [v setBackgroundColor:[UIColor grayColor]];
  22. [v setAlpha:0.6];
  23. [self.view addSubview:v];
  24. self.paintV = v;
  25.  
  26. [self addReturnBtn]; //添加返回按钮
  27. [self addDoodleSetWidthAndColor]; //增加设置涂鸦的宽度和颜色设置
  28. }
  29.  
  30. //添加返回按钮
  31. - (void)addReturnBtn{
  32. UIButton *returnBtn = [[UIButton alloc] initWithFrame:CGRectMake(, , , )];
  33. [returnBtn setTitle:@"返回" forState:UIControlStateNormal];
  34. [returnBtn addTarget:self action:@selector(returnPrePage) forControlEvents:UIControlEventTouchUpInside];
  35. [returnBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
  36. [self.view addSubview:returnBtn];
  37. }
  38.  
  39. //添加涂鸦宽度设置和颜色设置
  40. - (void)addDoodleSetWidthAndColor{
  41. //1、增加UISlider用来设置可调节宽度
  42. UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(, , , )];
  43. slider.maximumValue = 15.0f; //最大值
  44. slider.value = 3.0f; //默认为1
  45. self.paintV.lineWidth = slider.value;
  46. [slider addTarget:self action:@selector(setLineWidth:) forControlEvents:UIControlEventValueChanged]; //绑定值改变事件
  47. [self.view addSubview:slider];
  48.  
  49. //2、添加颜色选择按钮
  50. NSArray *colors = @[[UIColor redColor], [UIColor yellowColor], [UIColor greenColor], [UIColor blueColor], [UIColor purpleColor], [UIColor brownColor]];
  51. for (int i = ; i < colors.count; i++) {
  52. CGFloat x = + * i;
  53. UIButton *colorBtn = [[UIButton alloc] initWithFrame:CGRectMake(x, , , )];
  54. [colorBtn setBackgroundColor:[colors objectAtIndex:i]];
  55. [colorBtn addTarget:self action:@selector(setLineColor:) forControlEvents:UIControlEventTouchUpInside];
  56. [self.view addSubview:colorBtn];
  57. }
  58.  
  59. //第二行
  60. //3、添加撤销按钮
  61. UIButton *cancelBtn = [[UIButton alloc] initWithFrame:CGRectMake(, , , )];
  62. [cancelBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
  63. [cancelBtn setTitle:@"撤销" forState:UIControlStateNormal];
  64. [cancelBtn addTarget:self action:@selector(cancelPainting) forControlEvents:UIControlEventTouchUpInside];
  65. [self.view addSubview:cancelBtn];
  66.  
  67. //4、清屏按钮
  68. UIButton *clearScreenBtn = [[UIButton alloc] initWithFrame:CGRectMake(, , , )];
  69. [clearScreenBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
  70. [clearScreenBtn setTitle:@"清屏" forState:UIControlStateNormal];
  71. [clearScreenBtn addTarget:self action:@selector(clearScreen) forControlEvents:UIControlEventTouchUpInside];
  72. [self.view addSubview:clearScreenBtn];
  73.  
  74. //5、添加一个橡皮擦
  75. UIButton *brushBtn = [[UIButton alloc] initWithFrame:CGRectMake(, , , )];
  76. [brushBtn setTitle:@"橡皮擦" forState:UIControlStateNormal];
  77. [brushBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
  78. [brushBtn addTarget:self action:@selector(brush) forControlEvents:UIControlEventTouchUpInside];
  79. [self.view addSubview:brushBtn];
  80.  
  81. //6、保存到相册按钮
  82. UIButton *saveBtn = [[UIButton alloc] initWithFrame:CGRectMake(, , , )];
  83. [saveBtn setTitle:@"保存到相册" forState:UIControlStateNormal];
  84. [saveBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
  85. [saveBtn addTarget:self action:@selector(saveImgToAlbum) forControlEvents:UIControlEventTouchUpInside];
  86. [self.view addSubview:saveBtn];
  87. }
  88.  
  89. //调节宽度
  90. - (void)setLineWidth:(UISlider *)sender{
  91. [self.paintV setLineWidth:sender.value];
  92. }
  93.  
  94. //调节颜色
  95. - (void)setLineColor: (UIButton *)sender{
  96. [self.paintV setLineColor:sender.backgroundColor];
  97. }
  98.  
  99. //设置橡皮擦
  100. - (void)brush{
  101. self.paintV.lineColor = self.paintV.backgroundColor;
  102. if (self.paintV.lineWidth < ) self.paintV.lineWidth = ;
  103. }
  104. //撤销
  105. - (void)cancelPainting{
  106. [self.paintV cancelPainting];
  107. }
  108. //清屏
  109. - (void)clearScreen{
  110. [self.paintV clearScreen];
  111. }
  112.  
  113. //保存图片到相册
  114. - (void)saveImgToAlbum{
  115. [self.paintV saveImgToAlbum];
  116. }
  117.  
  118. //返回上一页
  119. - (void)returnPrePage{
  120. [self dismissViewControllerAnimated:YES completion:nil];
  121. }
  122.  
  123. - (void)didReceiveMemoryWarning {
  124. [super didReceiveMemoryWarning];
  125. // Dispose of any resources that can be recreated.
  126. }
  127.  
  128. /*
  129. #pragma mark - Navigation
  130.  
  131. // In a storyboard-based application, you will often want to do a little preparation before navigation
  132. - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
  133. // Get the new view controller using [segue destinationViewController].
  134. // Pass the selected object to the new view controller.
  135. }
  136. */
  137.  
  138. @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. javascript 入门——this属性的理解!

    JavaScript中函数的this对象是函数在执行时所处的作用域(例:当在网页的全局作用域中调用函数时,this对象引用的就是window). 例: window.color = "red ...

  2. 在Gridview如何进行每行单元格比较

    有在论坛上看到一个问题,就是在Gridview控件中,需要对几个列的数值进行比较,原问题如下: 先在数据库中准备数据: CREATE TABLE [dbo].[RecordTime] ( Id ,) ...

  3. Objective-C语法简记

    开始学习iPhone开发了,虽然现在已经有了Swift,但我还是老老实实地学习Objective-C,鄙人入门的程序语言是C,后来学习了C#和Java,现在来学Objective-C,这篇只是一些很简 ...

  4. Jquery请求Ajax的json数据

      获得单个json对象 $.getJSON("test.js", { name: "John", time: "2pm" }, funct ...

  5. SQL更改表字段为自增标识

    下面是SQL语句: --删除主键约束 ) select @Constraint_Name = Name from dbo.sysobjects where Xtype = 'PK' and Paren ...

  6. iOS 阶段学习第24天笔记(Block的介绍)

    iOS学习(OC语言)知识点整理 一.Block 的介绍 1)概念: block 是一种数据类型,类似于C语言中没有名字的函数,可以接收参数,也可以返回值与C函数一样被调用 封装一段代码 可以在任何地 ...

  7. 【译】About the Java Technology

    About the Java Technology Java technology is both a programming language and a platform. The Java Pr ...

  8. 身份证验证合法性js--已验证

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

  9. Eclipse使用多个Console

    调试程序时,有时需要同时使用多个Console,如一个Console运行Server,一个Console运行Client.而一般情况下Eclipse只有一个Console,这时就需要增加一个Conso ...

  10. AChartEngine绘制图形

    AChartEngine是Android作图的方法之一,要使用AChartEngine,首先下载AChartEngine,按照以下方法将其jar包添加到工程中: 1.将achartengine-1.1 ...