首页 > 学院 > 开发设计 > 正文

iOSUI进阶05

2019-11-14 18:25:51
字体:
来源:转载
供稿:网友
  • 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效果图:擦除前:效果图:擦除部分后

           


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表