Kingsly的iOS开发进阶专题

IOS-UI-Quartz2D

2015-06-21  本文已影响0人  雪鸮

IOS-UI-Quartz2D


1.quartz2d简述

Quartz 2D的API是一个纯C语言的,来自于Core Graphics跨家,所有的函数都以CG作为前缀;
quartz2d是一个而为绘图引擎,支持IOS和Mac,其能完成的工作如下:

实例:

01
02
03
04 05

2.图形上下文(Graphics Context)

07

输出的方式(上下文种类)


08

3.-drawRect

4.Quartz 2D绘图步骤(自定义View的步骤)

举例:

09 10

代码:

- (void)drawRect:(CGRect)rect {

CGContextRef ctx = UIGraphicsGetCurrentContext();

CGContextMoveToPoint(ctx, 10, 10);
CGContextAddLineToPoint(ctx, 100, 100);

CGContextStrokePath(ctx);
}

效果图:

11

5.路径绘制常用的方法 一

拼接路径的函数 CGContext + move../add..

  • 1.新建一个起点
    void CGContextMoveToPoint(CGContextRef c, CGFloat x, CGFloat y)
  • 2.添加新的线段到某个点
    void CGContextAddLineToPoint(CGContextRef c, CGFloat x, CGFloat y)
  • 3.添加一个矩形
    void CGContextAddRect(CGContextRef c, CGRect rect)
  • 4.添加一个椭圆
    void CGContextAddEllipseInRect(CGContextRef context, CGRect rect)
  • 5.添加一个圆弧
    void CGContextAddArc(CGContextRef c, CGFloat x, CGFloat y,
    CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)

绘制(渲染)路径的函数

  • 1.Mode参数决定绘制的模式
    void CGContextDrawPath(CGContextRef c, CGPathDrawingMode mode)
  • 2.绘制空心路径
    void CGContextStrokePath(CGContextRef c)
  • 3.绘制实心路径
    void CGContextFillPath(CGContextRef c)
    提示:一般以CGContextDraw、CGContextStroke、CGContextFill开头的函数,都是用来绘制路径的

应用实例:

- (void)set {
// 取的图形上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 创建起点
CGContextMoveToPoint(ctx, 10, 10);
// 添加线段至终点
CGContextAddLineToPoint(ctx, 100, 100);
//再次添加线段,默认以终点为起点
CGContextAddLineToPoint(ctx, 250, 100);


//添加矩形
CGContextAddRect(ctx, CGRectMake(20, 20, 100, 100));

// 添加椭圆
CGContextAddEllipseInRect(ctx, CGRectMake(130, 30, 100, 50));
CGContextMoveToPoint(ctx, 150, 300);
// 添加圆弧(注意,这里的顺时针逆时针方向是反着的)
CGContextAddArc(ctx, 100, 300, 50, 0, M_PI * 2, NO);

//渲染图形
CGContextStrokePath(ctx);   }

效果图:


12

注意:
1.贝瑟尔路径也存在currentpoint的问题,当你设置了一个currentpoint,也就意味着你重新开始了一个新的路径
2.路径绘制的代码不一定写到 - drawRect里边,只要在调用- drawRect方法的时候能够调用就好了

7.图像状态的设置

贝瑟尔路径:
这是一种OC对象,直接设置属性就可以了

path.lineWidth = 20;
path.lineJoinStyle = kCGLineJoinRound;
path.lineCapStyle = kCGLineCapButt;

颜色设置优点特殊:

[[UIColor greenColor] set];

上下文那种方法的状态设置:

 //设置状态
CGContextSetLineWidth(ctx, 30);//线条宽度
[[UIColor greenColor] set];//设置颜色
CGContextSetLineJoin(ctx, kCGLineJoinRound);//设置转角
CGContextSetLineCap(ctx, kCGLineCapButt);

技巧就是记住set:CGContextset......

8.绘图的完整过程解析

在一个view中只有一个图形上下文,而且是由系统帮我们创建好的,所以在我们获取图形上下文的时候你得到的是同一部分内存。
在这片内存之中,我们可以理解分为三部分,第一部分保存的是绘图信息,什么图形,第二部分是绘图状态,保存的是颜色,线宽,接头等等,第三部分是根据前边两部分的描述绘制出来的图形,在你执行渲染命令的时候,再从第三部分将图像移动到view上
注意:在执行一次stroke命令之后,图形路径信息就会被销毁掉,但是图形状态信息会被保留,除非你覆盖掉这些状态,否则一致存在,以后你在上下文上画的每一个图形都是这个状态(颜色,线宽等)

代码示例:

CGContextRef ctx = UIGraphicsGetCurrentContext();
//绘图路径信息
CGContextMoveToPoint(ctx, 100, 50);
CGContextAddLineToPoint(ctx, 100, 100);
CGContextAddLineToPoint(ctx, 200, 100);

//绘图状态信息
[[UIColor greenColor] set];
CGContextSetLineWidth(ctx, 20);
CGContextSetLineJoin(ctx, kCGLineJoinRound);
CGContextSetLineCap(ctx, kCGLineCapRound);

CGContextStrokePath(ctx);

结果:

13

如果将第二条线在第一条线渲染之后再加上:

 CGContextRef ctx = UIGraphicsGetCurrentContext();
//绘图路径信息
CGContextMoveToPoint(ctx, 100, 50);
CGContextAddLineToPoint(ctx, 100, 100);


//绘图状态信息
[[UIColor greenColor] set];
CGContextSetLineWidth(ctx, 20);
CGContextSetLineJoin(ctx, kCGLineJoinRound);
CGContextSetLineCap(ctx, kCGLineCapRound);

CGContextStrokePath(ctx);

//CGContextMoveToPoint(ctx, 200, 50);
CGContextAddLineToPoint(ctx, 200, 100);

//
CGContextStrokePath(ctx);

结果: 找不到起始点,说明前边的路径被销毁了

14

再次更改:添加起始点,观察颜色

CGContextRef ctx = UIGraphicsGetCurrentContext();
//绘图路径信息
CGContextMoveToPoint(ctx, 100, 50);
CGContextAddLineToPoint(ctx, 100, 100);


//绘图状态信息
[[UIColor greenColor] set];
CGContextSetLineWidth(ctx, 20);
CGContextSetLineJoin(ctx, kCGLineJoinRound);
CGContextSetLineCap(ctx, kCGLineCapRound);

CGContextStrokePath(ctx);

CGContextMoveToPoint(ctx, 200, 50);
CGContextAddLineToPoint(ctx, 200, 100);

//
CGContextStrokePath(ctx);

结果:运行正常

15

结论:执行一次渲染之后,图形路径信息被销毁,状态信息保留,只要不进行覆盖,将会一直保留

保存图形上下文状态的方法
利用CGContextSaveGState() 和CGContextRestoreGState(); 我们可以在保存一份纯洁的上下文,或者我们设置过的状态的上下文,然后再到我们需要的时候拿来用,比如:

示例代码:

 CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
//绘图路径信息
CGContextMoveToPoint(ctx, 100, 50);
CGContextAddLineToPoint(ctx, 100, 100);


//绘图状态信息
[[UIColor greenColor] set];
CGContextSetLineWidth(ctx, 20);
CGContextSetLineJoin(ctx, kCGLineJoinRound);
CGContextSetLineCap(ctx, kCGLineCapRound);

CGContextStrokePath(ctx);

CGContextRestoreGState(ctx);
CGContextMoveToPoint(ctx, 200, 50);
CGContextAddLineToPoint(ctx, 200, 100);

//
CGContextStrokePath(ctx);

结果:后边的那个线段就是没有设置状态之前的状态,我们是用保存的那个上下文图形状态来设置的

16

9.绘制文字和图片

绘制文字:新建文字,然后调用这个文字对象的draw...方法
绘制图片:新建图片,然后调用这个图片的draw...方法

示例代码:

  NSString *str = @"zhegjalsdjf;alsdjf;ajsdf";

[str drawInRect:CGRectMake(100, 100, 100, 100) withAttributes:nil];

结果:

17

补充:Attributes是属性的意思,这里可以给文字设置富文本属性,也就是一大堆的效果,通过新建一个字典,然后给字典加key-value来实现

示例代码:

NSString *str = @"zhegjalsdjf;alsdjf;ajsdf";

NSMutableDictionary *dic = [NSMutableDictionary dictionary];

dic[NSBackgroundColorAttributeName] = [UIColor redColor];
dic[NSFontAttributeName] = [UIFont systemFontOfSize:20];
dic[NSForegroundColorAttributeName] = [UIColor greenColor];


[str drawInRect:CGRectMake(100, 100, 100, 100) withAttributes:dic];

效果:

18

绘制图片代码示例:

UIImage *image = [UIImage imageNamed:@"CTO"];

[image drawAsPatternInRect:[UIScreen mainScreen].bounds];

// [image drawAsPatternInRect:CGRectMake(0, 0, 100, 100)];

  //[image drawAtPoint:CGPointMake(100, 100)];
//  上边这两种图片保持原来的大小

//[image drawInRect:CGRectMake(10, 10, 100, 100)];
//这种图片大小保持和rect一致

// [image drawInRect:CGRectMake(0, 0, 100, 100) blendMode:kCGBlendModeCopy alpha:1]; // 混合模式

效果:

19

注意:大部分的添加方法都是保持原来图片大小,drawinrect,会使图片与框框大小一致

9.旋转,缩放,平移

示例代码:

 CGContextRef ctx = UIGraphicsGetCurrentContext();


CGContextRotateCTM(ctx, M_PI_4); //旋转中心是坐标系的原点
CGContextTranslateCTM(ctx, [UIScreen mainScreen].bounds.size.width/2, 0);
CGContextScaleCTM(ctx, 0.5, 1);

CGContextMoveToPoint(ctx, 0, 0);
CGContextAddLineToPoint(ctx, 0, 200);

CGContextMoveToPoint(ctx, 0, 0);
CGContextAddLineToPoint(ctx, 2000, 0);

CGContextAddRect(ctx, CGRectMake(100, 100, 150, 150));

CGContextStrokePath(ctx);

效果图:

20

从这里比较容易的看出,这些移动啥的是咋弄的了;

10.裁减

示例代码:

CGContextRef ctx = UIGraphicsGetCurrentContext();

//画一个剪切的路径出来
CGContextAddArc(ctx, 100, 200, 50, 0, M_PI, NO);
//执行剪切的命令,确定剩下哪部分
CGContextClip(ctx);

//在要剩下的那部分添加图像
UIImage *image = [UIImage imageNamed:@"阿狸头像"];
[image drawInRect:CGRectMake(50, 200, 100, 50)];

效果:

21

注意:确定剪切路径要在剪切命令之前,添加图像要在剪切命令之后

上一篇 下一篇

猜你喜欢

热点阅读