• iOS_Quartz2D之涂鸦板


    响应者对象:继承了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 *)event
    101 {
    102     [self.touchPointView removeFromSuperview];
    103 }
    104 
    105 
    106 绘制view
    107 -(void)drawRect:(CGRect)rect
    108 {
    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 *)image
    129 {
    130     self.tuyaImage = image;
    131     [self setNeedsDisplay];
    132 }
    133 
    134 退后一步
    135 - (void)backTheLastTime
    136 {
    137     [self.linePaths removeLastObject];
    138     [self.penValues removeLastObject];
    139     [self.penColors removeLastObject];
    140     [self setNeedsDisplay];
    141 }
    142 
    143 清空画布
    144 - (void)cleanAllPainted
    145 {
    146     [self.linePaths removeAllObjects];
    147     [self.penValues removeAllObjects];
    148     [self.penColors removeAllObjects];
    149     self.tuyaImage = nil;
    150     [self setNeedsDisplay];
    151 }
    152 
    153 保存图片到手机相册
    154 - (void)savePicture
    155 {
    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 @end
    20 
    21 @implementation PropertyView
    22 
    23 -(void)viewDidLoad
    24 {
    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 *)sender
    44 {
    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 *)penColor
    12 {
    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)penValue
    19 {
    20     if (!_penValue) {
    21         _penValue = 1.0;
    22     }
    23     return _penValue;
    24 }
    View Code
  • 相关阅读:
    ireport制作小技巧
    Spring 自动装配 Bean
    Toad创建DBLINKsop
    Spring 读书笔记-----使用Spring容器(一)
    Spring读书笔记-----Spring的Bean之Bean的基本概念
    关于iOS开发中info.plist文件的解读
    iOS常用的第三方库GitHub地址
    NSUserDefault的使用
    论坛收集
    iOS开发的一些奇巧淫技
  • 原文地址:https://www.cnblogs.com/xiaoqiuge/p/4856473.html
Copyright © 2020-2023  润新知