美文网首页
Quartz 2D绘图 (2)再遇

Quartz 2D绘图 (2)再遇

作者: mojue | 来源:发表于2016-05-05 22:27 被阅读71次

    图片裁剪

    直接裁剪图片

    • 裁剪思路:

      • 绘制一个已经裁剪好的圆形的图形上下文
      • 将图片绘制上去就可以了
    • 代码

    // 1.获取图形上下文
    CGContextRef cxtRef = UIGraphicsGetCurrentContext();
    
    // 2.圆形路径对象
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 150) radius:50 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
    
    // 3.将路径对象添加到上下文
    CGContextAddPath(cxtRef, path.CGPath);
    
    // 3.2裁剪图形上下文,注意:必须是在添加完路径对象后,并且是渲染之前进行裁剪,否则没有意义。
    CGContextClip(cxtRef);
    
    // 4.渲染
    CGContextDrawPath(cxtRef, kCGPathStroke);
    
    // 5.绘制图片绘制图片需要在最后进行绘制
    UIImage *image = [UIImage imageNamed:@"me"];
    [image drawAtPoint:CGPointMake(100, 100)];
    
    

    保存到相册和沙盒

    > 相册

    • 保存到相册
    // 添加图片到相册中.  可选的监听方法格式如下:
    //  - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;
    UIKIT_EXTERN void UIImageWriteToSavedPhotosAlbum(UIImage *image, __nullable id completionTarget, __nullable SEL completionSelector, void * __nullable contextInfo);
    
    • 保存裁剪的图片
    // 保存裁剪的图片到相册
    UIImageWriteToSavedPhotosAlbum(imgCliped, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
    
    #pragma mark - 监听保存图片的成功与失败
    - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
        if (error) {
            NSLog(@"保存失败");
        } else {
            NSLog(@"保存成功");
        }
    }
    

    > 沙盒

    • 保存到沙盒

      • 获取文件路径
      • 将图片文件转为二进制数据
      • 将二进制数据写入到文件
    • 参考代码

    // 保存到沙盒
    // 文件路径
    NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"abc.png"];
    NSLog(@"%@", filePath);
    // 转为二进制文件
    NSData *imgData = UIImagePNGRepresentation(imgCliped);
    // 写入文件
    [imgData writeToFile:filePath atomically:YES];
    

    裁剪带圆环的图片

    • 裁剪思路:

      • 先绘制一个圆环
      • 再绘制要裁剪的图形
      • 最后在进行裁剪
    • 参考代码

      #pragma mark - 裁剪带圆环的图形
      // 加载图片显示
      UIImage *image = [UIImage imageNamed:@"me"];
      self.imgView.image = image;
      
      // 1.开启图片的图形上下文
      CGFloat margin = 10;
      CGSize size = CGSizeMake(image.size.width + 2 * margin, image.size.height + 2 * margin);
      UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
      
      // 2.获取当前的图形上下文
      CGContextRef cxtRef = UIGraphicsGetCurrentContext();
      
      // 圆心
      CGPoint center = CGPointMake(size.width * 0.5, size.height * 0.5);
      
      // 2.1绘制圆环
      // 半径 需要让圆环的半径刚好可以正其先换在最外面
      CGFloat radius = MIN(size.width, size.height) * 0.5 - margin * 0.5;
      // 圆环的路径
      UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:0 endAngle:M_PI * 2 clockwise:YES];
      
      CGContextSetLineWidth(cxtRef, margin);
      [[UIColor redColor] set];
      
      // 2.1.2添加
      CGContextAddPath(cxtRef, path.CGPath);
      // 2.2.3将圆环部分渲染
      CGContextDrawPath(cxtRef, kCGPathFill);
      
      // 2.2绘制要裁剪的图形
      CGFloat radius2 = MIN(image.size.width, image.size.height) * 0.5;
      UIBezierPath *path2 = [UIBezierPath bezierPathWithArcCenter:center radius:radius2 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
      // 2.2.2添加
      CGContextAddPath(cxtRef, path2.CGPath);
      
      // 5.裁剪
      CGContextClip(cxtRef);
      
      // 6.绘制图片
      [image drawAtPoint:CGPointMake(margin, margin)];
      
      // 7.从当前图形上下文中获取图片
      UIImage *imgClicped = UIGraphicsGetImageFromCurrentImageContext();
      
      UIGraphicsEndImageContext();
      
      self.imgView.image = imgClicped;
      

    裁剪带圆环的图片

    • 裁剪思路:

      • 先绘制一个圆环
      • 再绘制要裁剪的图形
      • 最后在进行裁剪
    • 参考代码

      #pragma mark - 裁剪带圆环的图形
      // 加载图片显示
      UIImage *image = [UIImage imageNamed:@"me"];
      self.imgView.image = image;
      
      // 1.开启图片的图形上下文
      CGFloat margin = 10;
      CGSize size = CGSizeMake(image.size.width + 2 * margin, image.size.height + 2 * margin);
      UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
      
      // 2.获取当前的图形上下文
      CGContextRef cxtRef = UIGraphicsGetCurrentContext();
      
      // 圆心
      CGPoint center = CGPointMake(size.width * 0.5, size.height * 0.5);
      
      // 2.1绘制圆环
      // 半径 需要让圆环的半径刚好可以正其先换在最外面
      CGFloat radius = MIN(size.width, size.height) * 0.5 - margin * 0.5;
      // 圆环的路径
      UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:0 endAngle:M_PI * 2 clockwise:YES];
      
      CGContextSetLineWidth(cxtRef, margin);
      [[UIColor redColor] set];
      
      // 2.1.2添加
      CGContextAddPath(cxtRef, path.CGPath);
      // 2.2.3将圆环部分渲染
      CGContextDrawPath(cxtRef, kCGPathFill);
      
      // 2.2绘制要裁剪的图形
      CGFloat radius2 = MIN(image.size.width, image.size.height) * 0.5;
      UIBezierPath *path2 = [UIBezierPath bezierPathWithArcCenter:center radius:radius2 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
      // 2.2.2添加
      CGContextAddPath(cxtRef, path2.CGPath);
      
      // 5.裁剪
      CGContextClip(cxtRef);
      
      // 6.绘制图片
      [image drawAtPoint:CGPointMake(margin, margin)];
      
      // 7.从当前图形上下文中获取图片
      UIImage *imgClicped = UIGraphicsGetImageFromCurrentImageContext();
      
      UIGraphicsEndImageContext();
      
      self.imgView.image = imgClicped;
      

    屏幕截图

    • 屏幕截图过程</br>
      • 开启图片的图形上下文
      • 获取当前的图形上下文
      • 将view的layer渲染到图形上下文中
      • 从当前的图形上下文中获取图片
    • 参考代码
      // 1.开启图片的图形上下文
      UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0.0);
      
      // 2.获取当前的图形上下文
      CGContextRef cxtRef = UIGraphicsGetCurrentContext();
      
      // 3.将view的layer渲染到图形上下文中
      [self.view.layer renderInContext:cxtRef];
      
      // 4.从当前的图形上下文中获取图片
      UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
      
      // 5.关闭图形上下文
      UIGraphicsEndImageContext();
      
      // 6.将图片保存到相册中
      UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil);
      

    触摸事件介绍

    • iOS中事件大体分为三类:触摸事件、加速计事件、远程控制事件
    • 需要掌握4中触摸事件
    • 不接受用户触摸事件的几种情况
    • 了解响应者链条
    • 手势识别

    4种触摸事件

    • 什么类型的对象是响应者对象呢?

      • 只要这个对象的类型是直接或者间接的继承自UIResponder,那么这个对象就是响应者对象。
    • 4种触摸事件

      #pragma mark - 当手指按下的时候调用
      - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
      #pragma mark - 当手指移动的时候调用
      - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
      #pragma mark - 当手指抬起的时候调用
      - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
      #pragma mark - 当有一些系统事件的时候调用,会打断对手指的跟踪行为
      - (void)touchesCancelled:(nullable NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
      
    • touches参数是NSSet类型

      • 特点是:1.无序 2.集合内的元素不重复
      • 遍历:可以通过forIn遍历
      • 取值:通过anyObject来获取对应的值
      • 在当前集合参数中装的都是UITouch类型的触摸对象
    • event参数是UIEvent类型

      • 用来区分是那种情况的触摸事件
      • 可以根据类型type和子类型subtype来确定是那种触摸事件。

    触摸事件的响应顺序和不接受触摸事件的几种情况

    • 触摸事件的响应顺序

      • 首先是最顶层的view被触发[第一响应者]
      • 然后是向下传,所有嵌套的view依次被触发
      • 控制器的view里面也是会被触发的。
    • 不接受触摸事件的几种情况

      • 1> 控件的hidden为YES的时候,不会触发
      • 2> 控件的User Interaction Enable 取消,不会触发
      • 3> 控件的父控件不能进行用户交互的时候,不会触发
      • 4> 控件的透明度小于等于0.01的时候,不会触发
      • 5> 控件不在父控件的有效范围内的时候,不会触发
      • 6> 图片框默认是不能接受用户交互的
      • 6> 对于按钮来说,按钮接收到用户事件后,会将用户响应事件切断,所以它的父控件就不会再去响应事件了。

    触摸事件的产生和传递过程

    • 触摸事件的产生

      • 当用户点击屏幕的时候就会产生UITouch类型的触摸对象,进而产生一系列的触摸事件
    • 触摸事件的传递过程

      • 1> 应用程序启动完毕后,内部就有一个运行循环,始终监听用户的触摸事件及其他的事件

      • 2> 首先,iOS监听到触摸点后,会把这个消息交给UIApplication对象,说"现在又触摸对象了,看一下按的是谁",

      • 3> UIApplication就直接告诉UIWindow"现在有用户触摸点了,看一下点的谁",

      • 4> 然后UIWindow就告诉控制器,现在有用户手指触摸屏幕,看一下是按到谁了,如果有导航控制器的及根控制器的话,会继续往下传递这个事件,传给最终在显示的控制器

      • 5> 最终显示的控制器拿到事件再传给它的view,控制器的view再搜索他自己的子控件,从后往前问,找到对应被点击的view。

      • 6> 找到被点击的view后,将消息一次返回说明找到了对应的view,应用程序再找对应view的注册事件,然后就执行对应的事件。前提是得基于触摸事件。

      • 7> 从用户触摸事件产生,然后从上往下传递事件。

      • 事件传递过程中涉及的方法有:

        • hitTest:当事件从上往下传的时候,递归查找那个view被点了。内部算法的原因会重复调用了两次

        • 控制器也是知道这个事件的,事件时通过控制器传递过来的

        • pointInside:WithEvent方法,确定事件到底在不在view内部。

        • hitTest就是用来测试控件是否可以响应事件。

    手势识别介绍

    • 在以前如果想监听一个view上的触摸事件,之前的做法是

      • 自定义一个view

      • 实现view的touches方法,在方法内部实现具体处理代码

      • 通过touches方法监听view的触摸事件,有很明显的几个缺点

        • 必须得自定义view
        • 由于是在view内部的touches方法中监听触摸事件,因此默认情况下,无法让其他外界对象监听view的触摸事件。
        • 不容易具体区分用户的具体手势行为
    • 在iOS3.2 之后,苹果退出了手势识别功能(Gesture Recognizer),在触摸事件处理方面,大大简化了开发者的开发难度。

    • 6种常用的手势识别器

      • UITapGestureRecognizer :轻按手势

      • UIPinchGestureRecognizer :缩放手势

      • UIRotationGestureRecognizer :旋转手势

      • UISwipeGestureRecognizer :清扫手势

      • UIPanGestureRecognizer :拖拽手势

      • UILongPressGestureRecognizer :长按手势

    • 手势识别的使用方法。
      实例化,指定监听方法
      添加到view上
      实现对应的方法。

    注意:imageView默认不支持多手势操作和用户交互,但是从媒体库拖入的图片是支持用户交互和多手势的。

    相关文章

      网友评论

          本文标题:Quartz 2D绘图 (2)再遇

          本文链接:https://www.haomeiwen.com/subject/owjrrttx.html