博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS_Quartz2D之涂鸦板
阅读量:6514 次
发布时间:2019-06-24

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

响应者对象:继承了UIResponder的对象

触摸事件:一根或多根手指;
开始触摸:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;

移动:每移动一点就会调用一次;

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;

触摸结束:

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;

触摸事件被打断:

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

远程控制事件:

- (void)remoteControlReceivedWithEvent:(UIEvent *)event NS_AVAILABLE_IOS(4_0);

UIToch对象:

触摸时,会为每个手指创建一个相关联的UITouch对象,保存着跟手指相关的信息,触摸的位置、时间等;

手指移动时,系统会更新同一个UITouch对象,一直保存手指触摸的位置;

手指移开时,销毁UITouch;

获取touch对象:UITouch * touch = [touches anyObject];

触摸点所在的view

touch.view

触摸点所在的window

touch.window

获取当前触摸点的位置,相对于哪个view的位置,填nil为相对于window;

    CGPoint point = [touch locationInView:touch.view];

获取上一个触摸点的位置,可以用于touchesMoved方法中

    CGPoint point2 = [touch previousLocationInView:touch.view];

 效果图:

         画笔笔头根据画笔宽度进行改变:

原理:利用view的触摸事件,使用UIBezierPath对象进行涂鸦,UIBezierPath可以储存线段上的所有点,当成一条路径使用,并且被渲染到视图上;根据触摸点位置变化设置跟踪笔头;

我仅仅实现了效果,封装的不是很好完善,推荐这位大神的博客,封装思想很好

我有一个继承自UIView的tuyaView来作为白色涂鸦板,一个设置画笔属性的UIViewController,一个用于储存画笔属性的数据manager类;

图片

步骤:

涂鸦板view:

1、自定义一个继承自UIView的view作为涂鸦板,UIView继承自UIResponder,可以接收触摸事件; 声明三个数组属性用于存放线段以及线段属性,并且在懒加载中初始化;

2、在viewtouchBegin事件中,新建一个UIBezierPath对象,使用它的moveToPoint方法将当前的触摸点设为这条线段的起点,并且将他存放到我们的线段数组中,从数据管理器中拿出线段的各种属性存放在属性数组中。初始化圆形画笔笔头,添加到涂鸦板上,中心位为触摸点;

4、监控手指的移动,将剩余线段点加入到上面创建的UIBezierPath对象中;从数组中取出贝塞尔对象,使用它的addLineToPoint方法,将移动后得到的当前点储存上;并且调用viewsetNeedDisplay方法,重绘view;设置画笔笔头跟踪手指触摸移动。当触摸结束时,将笔头view移除;

5、实现view的drawRect方法:此方法用于绘制view,第四步设置了每当touchmove时都会调用此方法,从数组中拿出每一个贝塞尔对象,将它画到view上,并且取出相应的画笔样式;如果用户选取了照片就将照片绘制上去,这样绘制功能就实现了;

6、实现添加图片、退一步、清空画布、保存图片四个方法;

tuyaView.m

1 @interface tuyaView ()  2 保存每条线段  3 @property (nonatomic, strong) NSMutableArray * linePaths;  4 保存每条线段的画笔大小  5 @property (nonatomic, strong) NSMutableArray * penValues;  6 保存每条线段颜色  7 @property (nonatomic, strong) NSMutableArray * penColors;  8 数据管理器  9 @property (nonatomic, strong) manager * m; 10 画笔 笔头; 11 @property (nonatomic, strong) UIView * touchPointView; 12  13 @end 14  15 @implementation tuyaView 16 懒加载中初始化各个数组 17 -(manager *)m 18 { 19     if (!_m) 20     { 21         _m = [manager shared]; 22     } 23     return _m; 24 } 25  26 -(NSMutableArray *)penValues 27 { 28     if (!_penValues) 29     { 30         _penValues = [NSMutableArray array]; 31     } 32     return _penValues; 33 } 34  35 - (NSMutableArray *)linePaths 36 { 37     if (!_linePaths) { 38         _linePaths = [NSMutableArray array]; 39     } 40     return _linePaths; 41 } 42  43 -(NSMutableArray *)penColors 44 { 45     if (!_penColors) { 46         _penColors = [NSMutableArray array]; 47     } 48     return _penColors; 49 } 50  51  52 触摸事件开始 53 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 54 { 55     UITouch * touch = [touches anyObject]; 56     CGPoint point = [touch locationInView:touch.view]; 57     // 58     UIBezierPath * linePath = [UIBezierPath bezierPath]; 59     [linePath moveToPoint:point]; 60     [self.linePaths addObject:linePath]; 61      62     //保存线条粗细 63     float penValue = self.m.penValue; 64     [self.penValues addObject:[NSNumber numberWithFloat:penValue ]]; 65     //保存线条颜色 66     UIColor * penColor = self.m.penColor; 67     [self.penColors addObject:penColor]; 68      69     //创建触控点 70     CGFloat touchRadius = self.m.penValue + 10; 71     self.touchPointView = [[UIView alloc] initWithFrame:CGRectMake(point.x - touchRadius * 0.5, point.y - touchRadius * 0.5, touchRadius, touchRadius)]; 72     self.touchPointView.layer.cornerRadius = touchRadius * 0.5; 73     self.touchPointView.clipsToBounds = YES; 74     self.touchPointView.backgroundColor = [UIColor redColor]; 75     self.touchPointView.alpha = 0.5; 76     [self addSubview:self.touchPointView]; 77 } 78  79 手指移动 80 -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 81 {     82     UITouch * touch = [touches anyObject]; 83     CGPoint touchPoint = [touch locationInView:touch.view]; 84      85     UIBezierPath * linePath = [self.linePaths lastObject]; 86     [linePath addLineToPoint:touchPoint]; 87      88     //触控点移动 89     CGPoint current = [touch locationInView:touch.view]; 90     CGPoint pre = [touch previousLocationInView:touch.view]; 91     CGPoint center = self.touchPointView.center; 92     center.x += current.x - pre.x; 93     center.y += current.y - pre.y; 94     self.touchPointView.center = center; 95      96     [self setNeedsDisplay]; 97 } 98  99 触摸结束100 -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event101 {102     [self.touchPointView removeFromSuperview];103 }104 105 106 绘制view107 -(void)drawRect:(CGRect)rect108 {109     [self.tuyaImage drawInRect:CGRectMake(0, 0, rect.size.width, rect.size.height)];110 111     for (int i = 0; i < self.linePaths.count; i ++)112     {113         UIBezierPath * path = self.linePaths[i];114         //取出线条宽度115         float penValue = [self.penValues[i] floatValue];116         [path setLineWidth:penValue];117         //取出线条颜色118         UIColor * color = self.penColors[i];119         [color setStroke];120         121         [path setLineJoinStyle:kCGLineJoinRound];122         [path setLineCapStyle:kCGLineCapRound];123         [path stroke];124     }125 }126 127 选取图片128 - (void)fetchPictureWith:(UIImage *)image129 {130     self.tuyaImage = image;131     [self setNeedsDisplay];132 }133 134 退后一步135 - (void)backTheLastTime136 {137     [self.linePaths removeLastObject];138     [self.penValues removeLastObject];139     [self.penColors removeLastObject];140     [self setNeedsDisplay];141 }142 143 清空画布144 - (void)cleanAllPainted145 {146     [self.linePaths removeAllObjects];147     [self.penValues removeAllObjects];148     [self.penColors removeAllObjects];149     self.tuyaImage = nil;150     [self setNeedsDisplay];151 }152 153 保存图片到手机相册154 - (void)savePicture155 {156     //1、开启上下文157     UIGraphicsBeginImageContextWithOptions(self.frame.size, YES, 0.0);158     //2、将控制器view的layer渲染到上下文,想要截啥就把哪个图层拿出来渲染159     [self.layer renderInContext:UIGraphicsGetCurrentContext()];160     //3、取出图片161     UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();162     //保存到手机相册163     UIImageWriteToSavedPhotosAlbum(newImage, nil, nil, nil);164     //关闭上下文165     UIGraphicsEndImageContext();166 }
View Code

属性控制器:1、从数据管理器中取出数据显示到自身view上。2、当画笔样式被修改时,将数据保存到管理器中。3、和tuyaView通过UINavigationController跳转,各种控件通过Storyboard实现;

PropertyView.m

1 @interface PropertyView () 2  3 @property (weak, nonatomic) IBOutlet UILabel *lalPen; 4 @property (weak, nonatomic) IBOutlet UISlider *slider; 5  6 @property (nonatomic, strong)manager * m; 7 @property (weak, nonatomic) IBOutlet UISlider *sliderRed; 8 @property (weak, nonatomic) IBOutlet UISlider *sliderGreen; 9 @property (weak, nonatomic) IBOutlet UISlider *sliderBlue;10 @property (weak, nonatomic) IBOutlet UISlider *sliderAlpha;11 12 @property (weak, nonatomic) IBOutlet UILabel *lalRed;13 @property (weak, nonatomic) IBOutlet UILabel *lalGreen;14 @property (weak, nonatomic) IBOutlet UILabel *lalBlue;15 @property (weak, nonatomic) IBOutlet UILabel *lalAlpha;16 17 @property (weak, nonatomic) IBOutlet UIView *colorView;18 19 @end20 21 @implementation PropertyView22 23 -(void)viewDidLoad24 {25     [super viewDidLoad];26     self.m = [manager shared];27     self.slider.value = self.m.penValue;28     self.lalPen.text = [NSString stringWithFormat:@"画笔宽度:%0.1lf",self.m.penValue];29     30     self.lalRed.text = self.lalRed.text = [NSString stringWithFormat:@"红:%0.0f",self.m.red];31     self.lalGreen.text = [NSString stringWithFormat:@"红:%0.0f",self.m.green];32     self.lalBlue.text = [NSString stringWithFormat:@"红:%0.0f",self.m.blue];33     self.lalAlpha.text = [NSString stringWithFormat:@"透明度:%0.0f",1 - self.m.penAlpha];34     35     self.sliderRed.value = self.m.red;36     self.sliderGreen.value = self.m.green;37     self.sliderBlue.value = self.m.blue;38     self.sliderAlpha.value = 1 - self.m.penAlpha;39     40     self.colorView.backgroundColor = self.m.penColor;41 }42 43 - (IBAction)PenSliderValueChanged:(UISlider *)sender44 {45     self.lalPen.text = [NSString stringWithFormat:@"画笔宽度:%0.1lf",sender.value];46     self.m.penValue = sender.value;47 }48 49 当4slider改变时回调同一个方法;50 - (IBAction)ColorChanged:(UISlider *)sender {51     switch (sender.tag) {52         case 1:53             self.lalRed.text = [NSString stringWithFormat:@"红:%0.0f",sender.value];54             self.m.red = sender.value;55             break;56         case 2:57             self.lalGreen.text = [NSString stringWithFormat:@"绿:%0.0f",sender.value];58             self.m.green = sender.value;59             break;60         case 3:61             self.lalBlue.text = [NSString stringWithFormat:@"蓝:%0.0f",sender.value];62             self.m.blue = sender.value;63             break;64         case 4:65             self.lalAlpha.text = [NSString stringWithFormat:@"透明度:%0.1f",sender.value];66             self.m.penAlpha = 1 - sender.value;67             break;68             69         default:70             break;71     }72     self.colorView.backgroundColor = self.m.penColor;73 }74 75 @end
View Code

数据管理器:储存画笔样式

manager.h

1 @interface manager : NSObject 2  3 @property (nonatomic, assign) CGFloat penValue; 4  5 @property (nonatomic, assign) CGFloat red; 6 @property (nonatomic, assign) CGFloat green; 7 @property (nonatomic, assign) CGFloat blue; 8 @property (nonatomic, strong) UIColor * penColor; 9 @property (nonatomic, assign) CGFloat penAlpha;10 11 + (instancetype)shared;12 13 @end
View Code

manager.m

1 + (instancetype)shared 2 { 3     static manager * m = nil; 4     static dispatch_once_t onceToken; 5     dispatch_once(&onceToken, ^{ 6         m = [[manager alloc] init]; 7     }); 8     return m; 9 }10 初始化颜色11 -(UIColor *)penColor12 {13     _penColor = [UIColor colorWithRed:self.red / 255 green:self.green/ 255 blue:self.blue / 255 alpha:1 - self.penAlpha];14     return _penColor;15 }16 17 初始化画笔宽度18 -(CGFloat)penValue19 {20     if (!_penValue) {21         _penValue = 1.0;22     }23     return _penValue;24 }
View Code

 

转载于:https://www.cnblogs.com/xiaoqiuge/p/4856473.html

你可能感兴趣的文章
Move-ADObject : 由于对象的父类不是未范例化就是被删除了,所以不能执行操作。...
查看>>
TypeScript+Vue 插件vue-property-decorator的使用总结
查看>>
grep 命令
查看>>
Cut
查看>>
高级网络综合实战架构案例
查看>>
Unity HoloLens开发配置
查看>>
CentOS 6 kickstart 部署脚本
查看>>
Java集合工具类(二)-泛型集合工具类,用于便捷快速的定义、操作集合。包含Set的交集、并集......
查看>>
Linux 虚拟文件系统和进程的关系
查看>>
进程通信:管道和socketpair的
查看>>
Windows2008计划任务运行powershell脚本故障解决
查看>>
近视者的福音!谷歌眼镜将推出“处方版”
查看>>
zabbix agent 监控Linux
查看>>
Weka开发[13]-Ensemble
查看>>
揭秘xp系统中一些不经常使用的技巧
查看>>
TCP/IP那点事儿 协议那些事儿
查看>>
ActiveMQ的消息重发策略和DLQ处理
查看>>
我的友情链接
查看>>
执行shell的三种方法
查看>>
【机器学习实战】第1章 机器学习基础
查看>>