zoukankan      html  css  js  c++  java
  • iOS UI进阶05

    • Quartz2D
      • Quartz2D是二维的绘图引擎
        • 经包装的函数库,方便开发者使用。也就是说苹果帮我们封装了一套绘图的函数库
        • 用Quartz2D写的同一份代码,既可以运行在iphone上又可以运行在mac上,可以跨平台开发。
        • 开发中比较常用的是截屏/裁剪/自定义UI控件。 Quartz2D在iOS开发中的价值就是自定义UI控件。
        • 在drawRect:方法中才能获取到上下文
    • Quartz2D绘图
      • 自定义view:需要绘图,就必须重写drawRect:方法
        • 1 drawRect视图要显示的时候,才会调用,viewDidLoad后才会调用,因为那时候还没显示视图。
        • 2 作用:用来绘图
          • 画一条线
          • 1 获取图形上下文
          • CG:表示这个类在CoreGraphics框架里 Ref:引用
          • 想获取图形上下文,首先敲UIGraphics。
          • 2 拼接路径:一般开发中用贝塞尔路径,里面封装了很多东西,可以帮我画一些基本的线段,矩形,圆等等。
          • 创建贝塞尔路径
          • 起点:moveToPoint
          • 终点:addLineToPoint
          • 3 把路径添加到上下文
        • CGPath转换:UIKit框架转CoreGraphics直接CGPath就能转
          • 4> 把上下文渲染到视图,图形上下文本身不具备显示功能。
          • 5总结:首先获取图形上下文,然后描述路径,把路径添加到上下文,渲染到视图,图形上下文相当于一个内存缓存区,在内存里面操作是最快的,比直接在界面操作快多了。
          • // 什么时候调用:当前控件即将显示的时候才会调用这个方法绘制
               // 作用:绘制内容,以后只要想在一个view中绘制内容,必须在drawRect里面绘制
               - (void)drawRect:(CGRect)rect {
            
                // 绘制曲线
                // 1.获取上下文
                CGContextRef ctx = UIGraphicsGetCurrentContext();
            
                // 2.拼接路径
                UIBezierPath *path = [UIBezierPath bezierPath];
            
                // 设置起点
                [path moveToPoint:CGPointMake(10, 125)];
            
                // 描述曲线
                [path addQuadCurveToPoint:CGPointMake(240, 125) controlPoint:CGPointMake(125, 240)];
            
                [path addLineToPoint:CGPointMake(10, 125)];
            
                // 3.添加路径到上下文
                CGContextAddPath(ctx, path.CGPath);
            
                // 设置绘图状态,一定要再渲染之前
                // 设置颜色
                [[UIColor redColor] setStroke];
            
                // 设置线段的宽度
                CGContextSetLineWidth(ctx, 15);
                // 设置线段的顶角样式
                CGContextSetLineCap(ctx, kCGLineCapRound);
            
                // 设置连接样式
                CGContextSetLineJoin(ctx, kCGLineJoinRound);
            
                // 4.渲染上下文
                CGContextStrokePath(ctx);
            }
        • 画两跟不连接的线
          • 1 第二次画的时候,重新设置起点,然后画线。一个路径可以包含多条线段。
          • 2 新创建一个路径,添加到上下文。开发中建议使用这种,比较容易控制每根线。
          • // 绘制两条路径的方法
            - (void)drawTwoLine
            {
                // 1.获取上下文
                CGContextRef ctx = UIGraphicsGetCurrentContext();
            
                // 2.拼接路径,一个路径中可以保存多条线段
                UIBezierPath *path = [UIBezierPath bezierPath];
            
                [path moveToPoint:CGPointMake(10, 10)];
            
                [path addLineToPoint:CGPointMake(20, 20)];
            
            
                // 3.把路径添加到上下文
                CGContextAddPath(ctx, path.CGPath);
            
                // 一根线对应一个路径,只要绘制的线不连接,最好使用一根线对应一个路径的方法
                path = [UIBezierPath bezierPath];
                // 拼接另一根直线
                // 默认下一根线的起点就是上一根线的终点
                // 设置第二根线的起点
                //    [path moveToPoint:CGPointMake(20, 20)];
                // 如果想要绘制不连接的线,重新设置起点
                [path moveToPoint:CGPointMake(50, 50)];
            
                [path addLineToPoint:CGPointMake(20, 200)];
            
                // 3.把路径添加到上下文
                CGContextAddPath(ctx, path.CGPath);
            
                // 4.渲染上下文
                CGContextStrokePath(ctx);
            
            }
        • 圆弧
          • 分析:
            • 1> 圆弧属于圆的一部分,因此先要有圆,才有弧。
            • 2> 圆需要起点吗?画线需要,圆也不另外。 -3> 起点在哪? 圆心右边
            • 4> 画圆弧还需要起始角度,结束角度,方向,角度必须是弧度
            • // 画圆弧
                  // Center圆心
                  // radius:半径
                  // startAngle起始角度
                  // endAngle:结束角度
                  // clockwise:Yes 顺时针 No逆时针
                  CGPoint center = CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.height * 0.5);
                  UIBezierPath *path1 = [UIBezierPath bezierPathWithArcCenter:center radius:100 startAngle:0 endAngle:M_PI_2 clockwise:NO];
              
                  [path1 stroke];
        • 画扇形
          • // 画扇形
                UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:100 startAngle:0 endAngle:M_PI_2 clockwise:YES];
            
                [path addLineToPoint:center];
            
                [path addLineToPoint:CGPointMake(self.bounds.size.height * 0.5 + 100, self.bounds.size.height * 0.5)];
                // 关闭路径:从路径的终点连接到起点
                [path closePath];
                // 设置填充颜色
                [[UIColor redColor] setFill];
            
                // 设置描边颜色
                [[UIColor greenColor] setStroke];
            
                //    [path stroke];
                // 如果路径不是封闭的,默认会关闭路径
                [path fill];
        • 画饼图
          • #import "PieView.h"
            
            @implementation PieView
            
            
            // Only override drawRect: if you perform custom drawing.
            // An empty implementation adversely affects performance during animation.
            
            - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
            {
               //重绘
                [self setNeedsDisplay];
            }
            
            - (void)drawRect:(CGRect)rect {
                // Drawing code
            
                NSArray *data = @[@25,@25,@20,@30];
            
                //圆心
                CGPoint center = CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.height * 0.5);
                //角度
                CGFloat radius = self.bounds.size.width * 0.5;
                CGFloat startA = 0;
                CGFloat endA = 0;
                CGFloat angle = 0;
            
                for (NSNumber *num in data) {
                    // 画一个扇形
                    startA = endA;
                    angle = [num intValue] / 100.0 * M_PI * 2;
                    endA = startA + angle;
            
                   UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];
            
                    [path addLineToPoint:center];
            
                    // set:同时设置描边和填充颜色
                    [[self randomColor] set];
            
                    [path fill];
            
                }
            
            }
            
            // 随机颜色
            - (UIColor *)randomColor
            {
                CGFloat r = arc4random_uniform(256) / 255.0;
                CGFloat g = arc4random_uniform(256) / 255.0;
                CGFloat b = arc4random_uniform(256) / 255.0;
                return [UIColor colorWithRed:r green:g blue:b alpha:1];
            }
            
            
            
            @end
            效果图

        • 画字
          • - (void)drawRect:(CGRect)rect {
            
                NSString *str = @"hello!";
            
                // Attributes:属性
                // 给一个字符串添加属性,可以叫富文本,颜色,字体大小,空心,阴影
            
                // 利用这个属性字典给文本添加属性
                NSMutableDictionary *strAttr = [NSMutableDictionary dictionary];
                // key,value
                // 如何找到设置文本的属性key
                // 描述了字体
                strAttr[NSFontAttributeName] = [UIFont boldSystemFontOfSize:50];
            
                // 设置描边的颜色和宽度
                strAttr[NSStrokeWidthAttributeName] = @1;
            
                strAttr[NSStrokeColorAttributeName] = [UIColor redColor];
            
                NSShadow *shadow = [[NSShadow alloc] init];
            
                shadow.shadowColor = [UIColor yellowColor];
            
                shadow.shadowOffset = CGSizeMake(10, 10);
            
                shadow.shadowBlurRadius = 5;
            
                // 阴影
                strAttr[NSShadowAttributeName] = shadow;
            
                // 文字颜色
                strAttr[NSForegroundColorAttributeName] = [UIColor redColor];
            
                [str drawAtPoint:CGPointZero withAttributes:strAttr];
            
            }
             效果图:
      • 定时器实现下雪
          • #import "SnowView.h"
            
            @implementation SnowView
            
            
            - (void)awakeFromNib
            {
                // 设置定时器
            //    [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(setNeedsDisplay) userInfo:nil repeats:YES];
            
                // 0.1 setNeedsDisplay 绑定一个标识,等待下次刷新的时候才会调用drawRect方法
                // 0.15 屏幕的刷新时间
            
                // 定时器
                // 每次屏幕刷新的时候就会调用,屏幕一秒刷新60次
                CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(setNeedsDisplay)];
            
                // 只要把定时器添加到主运行循环就能自动执行
                [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
            
                // setNeedsDisplay:底层并不会马上调用drawRect,只会给当前的控件绑定一个刷新的标识,每次屏幕刷新的时候,就会把绑定了刷新(重绘)标识的控件重新刷新(绘制)一次,就会调用drawRect去重绘
            
                // 如果以后每隔一段时间需要重绘,一般不使用NSTimer,使用CADisplayLink,不会刷新的时候有延迟
            }
            
            // Only override drawRect: if you perform custom drawing.
            // An empty implementation adversely affects performance during animation.
            - (void)drawRect:(CGRect)rect {
                // Drawing code
            
                static CGFloat snowY = 0;
            
                UIImage *image = [UIImage imageNamed:@"雪花"];
            
                [image drawAtPoint:CGPointMake(0, snowY)];
            
                snowY += 10;
            
                if (snowY > rect.size.height) {
                    snowY = 0;
                }
            
            
            }
            效果图:
      • 图形上下文状态栈
          • #import "DrawView.h"
            
            @implementation DrawView
            
            
            // Only override drawRect: if you perform custom drawing.
            // An empty implementation adversely affects performance during animation.
            - (void)drawRect:(CGRect)rect {
                // Drawing code
                // 1.获取上下文
                CGContextRef ctx = UIGraphicsGetCurrentContext();
            
                // 2.拼接路径
                UIBezierPath *path = [UIBezierPath bezierPath];
            
                [path moveToPoint:CGPointMake(10, 125)];
            
                [path addLineToPoint:CGPointMake(240, 125)];
            
                // 3.把路径添加到上下文
                CGContextAddPath(ctx, path.CGPath);
            
                // 保存当前上下文的默认状态
                CGContextSaveGState(ctx);
            
                // 设置状态
                [[UIColor redColor] set];
            
                CGContextSetLineWidth(ctx, 20);
            
                // 渲染上下文
                CGContextStrokePath(ctx);
            
                // 创建第二根路径
                path = [UIBezierPath bezierPath];
                [path moveToPoint:CGPointMake(125, 10)];
                [path addLineToPoint:CGPointMake(125, 240)];
            
                // 添加到上下文
                CGContextAddPath(ctx, path.CGPath);
            
                // 恢复下上下文状态
                // 取出之前的保存的状态覆盖掉当前的状态
                CGContextRestoreGState(ctx);
            //    [[UIColor blackColor] set];
            //    CGContextSetLineWidth(ctx, 1);
            
                // 4.渲染上下文到view的layer
                // 在渲染之前,系统会查看下上下文的状态,根据状态去渲染
                CGContextStrokePath(ctx);
            
            }
            
            @end

        • 图片截屏
          • #import "ViewController.h"
            
            @interface ViewController ()
            
            @property (nonatomic, weak) UIView *cover;
            
            @property (nonatomic, assign) CGPoint oriP;
            
            @property (weak, nonatomic) IBOutlet UIImageView *imageView;
            @property (weak, nonatomic) IBOutlet UIView *view1;
            
            @end
            
            @implementation ViewController
            
            - (UIView *)cover
            {
                if (_cover == nil) {
                    UIView *view = [[UIView alloc] init];
            
            
                    view.backgroundColor = [UIColor blackColor];
                    view.alpha = 0.5;
            
                    _cover = view;
            
                    [self.view addSubview:view];
            
                }
                return _cover;
            }
            
            - (IBAction)pan:(UIPanGestureRecognizer *)sender {
                // 获取下当前的触摸
                CGPoint curP = [sender locationInView:_imageView];
                if (sender.state == UIGestureRecognizerStateBegan) {
                    // 记录下一开始的位置
                    _oriP = curP;
                }
            
                // 计算下黑色蒙版的frame
                CGFloat w = curP.x - _oriP.x;
                CGFloat h = curP.y - _oriP.y;
            
                self.cover.frame = CGRectMake(_oriP.x, _oriP.y, w, h);
            
            
                if (sender.state == UIGestureRecognizerStateEnded) { // 手指抬起
            
                    // 裁剪图片,生成一张新图片
            
                    // 开启位图上下文
                    UIGraphicsBeginImageContextWithOptions(_imageView.bounds.size, NO, 0);
            
                    // 设置裁剪区域
                    UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.cover.frame];
                    [path addClip];
            
            
                    // 绘制图片
                    [_imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
            
                    // 生成图片
                    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
            
                    // 关闭上下文
                    UIGraphicsEndImageContext();
            
                    _imageView.image = image;
            
                    [self.cover removeFromSuperview];
            
            
                }
            
            
            }
            @end
            效果图:截屏前
            效果图:截屏后
             
        • 图片擦除
          • #import "ViewController.h"
            
            @interface ViewController ()
            
            @end
            
            @implementation ViewController
            // 只要用户手指在图片上拖动.就会调用
            - (IBAction)pan:(UIPanGestureRecognizer *)sender {
                // 拖动的时候,擦除图片的某一部分
            
                // 获取手指的触摸点
               CGPoint curP = [sender locationInView:sender.view];
            
                // 计算擦除的frame
                CGFloat wh = 30;
                CGFloat x = curP.x - wh * 0.5;
                CGFloat y = curP.y - wh * 0.5;
            
                CGRect frame = CGRectMake(x, y, wh, wh);
            
                // 开启位图上下文
                UIGraphicsBeginImageContextWithOptions(sender.view.bounds.size, NO, 0);
            
                // 获取当前的上下文
                CGContextRef ctx = UIGraphicsGetCurrentContext();
            
                // 把控件上的内容渲染到上下文
                [sender.view.layer renderInContext:ctx];
            
                // 清除上下文中某一部分的内容
                CGContextClearRect(ctx, frame);
            
                // 生成一张新的图片
                UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
            
                // 关闭上下文
                UIGraphicsEndImageContext();
            
                // 重新显示到UIImageView
                UIImageView *imageV = (UIImageView *)sender.view;
            
                imageV.image = image;
            
            }
            
            @end
            效果图:擦除前:
            效果图:擦除部分后
  • 相关阅读:
    【原创翻译】给前端小白的现代JavaScript工作流程详解 | Modern JavaScript Explained For Dinosaurs
    JavaScript音频可视化
    CSS两种布局记录
    飞桨|PaddlePaddle YoloV3学习笔记
    飞桨|PaddlePaddle第二周学习笔记|卷积神经网络、计算机视觉相关知识
    求所有不重复路径, Unique Paths | 换硬币问题 LeetCode题解(四)
    最大子数组,Maximum Subarray| Best Time to Buy and Sell Stock, LeetCode题解(三)
    合并k个有序链表, LeetCode题解(二)
    TwoSum, ThreeSum, 数字链表相加, LeetCode题解(一)
    最长公共子序列、最长重复子串
  • 原文地址:https://www.cnblogs.com/liujiaoxian/p/4770420.html
Copyright © 2011-2022 走看看