iOS开发-Quartz 2D简介(一)

什么是Quartz2D?

Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统

Quartz 2D的API是纯C语言的来自于Core Graphics框架数据类型和函数都是以CG为前缀

CGContextRef\CGPathRef\CGContextStrokePath(ctx)

 

Quartz 2D能完成的工作

绘制图形 : 线条\三角形\矩形\圆\弧等

绘制文字

绘制\生成图片(图像)

读取\生成PDF

截图\裁剪图片

自定义UI控件

......

 

Quartz2D在iOS开发中的价值?

为了便于搭建美观的UI界面,iOS提供了UIKit框架,里面有各种各样的UI控件

UILabel:显示文字

UIImageView:显示图片

UIButton:同时显示图片和文字(能点击)

......

1>利用UIKit框架提供的控件,拼拼凑凑,能搭建和现实一些简单、常见的UI界面

2>但是,有些UI界面极其复杂、而且比较个性化,用普通的UI控件无法实现,这时可以利用Quartz2D技术将控件内部的结构画出来,自定义控件的样子

3>其实,iOS中大部分控件的内容都是通过Quartz2D画出来的

4>因此,Quartz2D在iOS开发中很重要的一个价值是:自定义view(自定义UI控件)

5>那么废话不多说,直接上

 

 

图形上下文

图形上下文(Graphics Context):是一个CGContextRef类型的数据

图形上下文的作用

保存绘图信息、绘图状态

决定绘制的输出目标(绘制到什么地方去?)

 

(输出目标可以是PDF文件、Bitmap或者显示器的窗口上)

相同的一套绘图序列,指定不同的Graphics Context,就可将相同的图像绘制到不同的目标上

 

 

 

 

//

//  ViewController.h

//  Quartz2D

//

//  Created by 周昭 on 16/4/8.

//  Copyright © 2016年 Jordan Zhou. All rights reserved.

//

 

#import <UIKit/UIKit.h>

 

@interface ViewController : UIViewController

 

@end

 

 

//

//  ViewController.m

//  Quartz2D

//

//  Created by 周昭 on 16/4/8.

//  Copyright © 2016年 Jordan Zhou. All rights reserved.

//

 

#import "ViewController.h"

#import "ZZQuartz2D.h"

 

@interface ViewController ()

@property (nonatomic, weak) ZZQuartz2D *drawViw;

@end

 

@implementation ViewController

 

- (void)viewDidLoad {

    [super viewDidLoad];

    

    // 加载绘图view

    [self setUpQuartz2DView];

    

    // 重绘slider

    [self setUpSlider];

 

}

 

/**

 *  添加绘图view

 */

- (void)setUpQuartz2DView

{

    ZZQuartz2D *drawViw = [[ZZQuartz2D alloc] initWithFrame:[UIScreen mainScreen].bounds];

    drawViw.backgroundColor = [UIColor whiteColor];

    [self.view addSubview:drawViw];

    self.drawViw = drawViw;

}

 

/**

 *  创建slider

 */

- (void)setUpSlider

{

    UISlider *slider = [[UISlider alloc] init];

    slider.minimumValue = 0;

    slider.maximumValue = 100;

    CGFloat sliderX = self.view.frame.size.width * 0.5;

    CGFloat sliderY = self.view.frame.size.height * 0.7;

    CGFloat sliderW = self.view.frame.size.width * 0.8;

    CGFloat sliderH = 20;

    slider.center = CGPointMake(sliderX, sliderY);

    slider.bounds = CGRectMake(0, 0, sliderW, sliderH);

    [self.view addSubview:slider];

    

    // 类似于UISlider\UISwitch 这样的控件事件改变是其值的改变

    [slider addTarget:self action:@selector(sizeChange:) forControlEvents:UIControlEventValueChanged];

    

}

 

/**

 *  根据set方法来赋值并且在内部调用  setNeedsDisplay 重绘的方法

 */

- (void)sizeChange:(UISlider *)slider

{

    self.drawViw.radius = slider.value;

}

 

@end

 

//

//  ZZQuartz2D.h

//  Quartz2D

//

//  Created by 周昭 on 16/4/8.

//  Copyright © 2016年 Jordan Zhou. All rights reserved.

//

 

#import <UIKit/UIKit.h>

 

@interface ZZQuartz2D : UIView

 

/**

 *  圆的半径

 */

@property (nonatomic, assign) float radius;

 

@end

 

//

//  ZZQuartz2D.m

//  Quartz2D

//

//  Created by 周昭 on 16/4/8.

//  Copyright © 2016年 Jordan Zhou. All rights reserved.

//

 

#import "ZZQuartz2D.h"

 

@interface ZZQuartz2D()

 

@property (nonatomic, assign) CGFloat snowY;

 

@end

 

@implementation ZZQuartz2D

 

/**

 *  重写set方法

 */

- (void)setRadius:(float)radius

{

    _radius = radius;

    

    // 重绘的方法只能是自己调用

    [self setNeedsDisplay];

}

 

/**

 *  当你创建view的时候这个方法就会自动创建可见这个方法的重要性

 */

- (void)drawRect:(CGRect)rect {

#warning 这个方法只会调一次走一次

    /*

     drawLine();  画线

     graphicsContextStack();  图形上下文栈(重点:这个原理流程见分析思路)

     draw4Rect();  画四边形

     drawTriangle();  画三角形

     drawArc();  画圆弧

     drawCircle();  画圆

     drawCircle4(); 画1/4圆

     drawImage(); 画图片

     drawText();  画文字

     matrixOperation();  矩阵操作

     [self reDrawCircle];  重绘(刷帧)

     [self drawSnowAnimation];  画出下雪的效果

     */

}

 

/**

 *  画线\多条线\区分线段样式

 */

void drawLine()

{

    // 1.获得图形上下文

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    

    // 2.拼接图形(路径)

    CGContextSetLineWidth(ctx, 10);

    

    // 设置线段头尾部的样式

    CGContextSetLineCap(ctx, kCGLineCapRound);

    

    // 设置线段转折点的样式

    CGContextSetLineJoin(ctx, kCGLineJoinRound);

    

#pragma mark ---- 这里要求区分画出俩条线它们的属性即 线宽\颜色\转角点不一样 这是一种做法 重新设置属性然后多次渲染

    /**  第1根线段  **/

    // 设置颜色

    CGContextSetRGBStrokeColor(ctx, 1, 0, 0, 1);

    // 设置一个起点

    CGContextMoveToPoint(ctx, 10, 10);

    // 添加一条线段到(100, 100)

    CGContextAddLineToPoint(ctx, 100, 100);

    

    // 渲染一次

    CGContextStrokePath(ctx);

    

    /**  第2根线段  **/

    // 设置颜色

    CGContextSetRGBStrokeColor(ctx, 0, 0, 1, 1);

    // 设置一个起点

    CGContextMoveToPoint(ctx, 200, 190);

    // 添加一条线段到(150, 40)

    CGContextAddLineToPoint(ctx, 130, 50);

    CGContextAddLineToPoint(ctx, 100, 70);

    

    // 3.渲染显示到view上面

    CGContextStrokePath(ctx);

}

 

/**

 *  图形上下文栈

 */

void graphicsContextStack()

{

    // 1.获得上下文

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    

    // 将ctx拷贝一份放到栈中

    CGContextSaveGState(ctx);

    

    // 设置绘图状态

    CGContextSetLineWidth(ctx, 10);

    [[UIColor redColor] set];

    CGContextSetLineCap(ctx, kCGLineCapRound);

    

    // 第1根线

    CGContextMoveToPoint(ctx, 50, 50);

    CGContextAddLineToPoint(ctx, 120, 190);

    

    CGContextStrokePath(ctx);

    

    // 将栈顶的上下文出栈,替换当前的上下文

    CGContextRestoreGState(ctx);

    

    

    // 第2根线

    CGContextMoveToPoint(ctx, 10, 70);

    CGContextAddLineToPoint(ctx, 220, 290);

    

    CGContextStrokePath(ctx);

    //    CGContextDrawPath(ctx, kCGPathStroke); 这个相比传递参数还多一点为什么不记住简单?

}

 

/**

 *  画四边形

 */

void draw4Rect()

{

    // 1.获得上下文

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    

    // 2.画矩形

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

    

    // set : 同时设置为实心和空心颜色

    // setStroke : 设置空心颜色

    // setFill : 设置实心颜色

    [[UIColor whiteColor] set];

    

    //    CGContextSetRGBFillColor(ctx, 0, 0, 1, 1);

    

    // 3.绘制图形

    CGContextFillPath(ctx);

}

 

/**

 *  画三角形

 */

void drawTriangle()

{

    // 1.获得上下文

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    

    // 2.画三角形

    CGContextMoveToPoint(ctx, 0, 0);

    CGContextAddLineToPoint(ctx, 100, 100);

    CGContextAddLineToPoint(ctx, 150, 80);

    // 关闭路径(连接起点和最后一个点)

    CGContextClosePath(ctx); // CGContextAddLineToPoint(ctx, 0, 0); 在连回去也是ok的

    

    CGContextSetRGBStrokeColor(ctx, 0, 1, 0, 1);

    

    // 3.绘制图形

    CGContextStrokePath(ctx);

}

 

/**

 *  画圆弧

 */

void drawArc()

{

    // 1.获得上下文

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    

    // 2.画圆弧

    // x\y : 圆心

    // radius : 半径

    // startAngle : 开始角度

    // endAngle : 结束角度

    // clockwise : 圆弧的伸展方向(0:顺时针, 1:逆时针)

    CGContextAddArc(ctx, 100, 100, 50, M_PI_2, M_PI, 0);

    

    // 3.显示所绘制的东西

    CGContextFillPath(ctx);

}

 

/**

 *  画圆

 */

void drawCircle()

{

    // 1.获得上下文

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    

    // 2.画圆

    CGContextAddEllipseInRect(ctx, CGRectMake(50, 10, 100, 100));

    

    CGContextSetLineWidth(ctx, 10);

    

    // 3.显示所绘制的东西

    CGContextStrokePath(ctx);

}

 

/**

 *  画1/4圆

 */

void drawCircle4() 

{

    // 1.获得上下文

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    

    // 2.画1/4圆

    CGContextMoveToPoint(ctx, 100, 100);

    CGContextAddLineToPoint(ctx, 100, 150);

    CGContextAddArc(ctx, 100, 100, 50, -M_PI_2, M_PI, 1);

    CGContextClosePath(ctx);

    

    [[UIColor redColor] set];

    

    // 3.显示所绘制的东西

    CGContextFillPath(ctx);

}

 

/**

 *  画图片

 */

void drawImage()

{

    // 1.取得图片

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

    

    // 2.画

    /*

    [image drawAtPoint:CGPointMake(50, 50)]; // 画在那个点

    [image drawInRect:CGRectMake(0, 0, 150, 150)]; // 画在一个矩形框内

    */

    [image drawAsPatternInRect:CGRectMake(0, 0, 200, 200)]; // 平铺

 

    // 3.画文字

    NSString *str = @"xxx所画";

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

}

 

/**

 *  画文字

 */

void drawText()

{

    // 1.获得上下文

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    

    // 2.画矩形

    CGRect cubeRect = CGRectMake(50, 50, 100, 100);

    CGContextAddRect(ctx, cubeRect);

    

    // 3.显示所绘制的东西

    CGContextFillPath(ctx);

    

    // 4.画文字

    NSString *str = @"My mood is so bad!!!";

    //    [str drawAtPoint:CGPointZero withAttributes:nil];

    

    NSMutableDictionary *attrs = [NSMutableDictionary dictionary];

    // NSForegroundColorAttributeName : 文字颜色

    // NSFontAttributeName : 字体

    attrs[NSForegroundColorAttributeName] = [UIColor redColor];

    attrs[NSFontAttributeName] = [UIFont systemFontOfSize:50];

    [str drawInRect:cubeRect withAttributes:attrs];

}

 

/**

 *  矩阵操作

 */

void matrixOperation()

{

    // 1.获得上下文

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    

    // 将ctx拷贝一份放到栈中

    CGContextSaveGState(ctx);

    

    CGContextRotateCTM(ctx, M_PI_4 * 0.3);

    CGContextScaleCTM(ctx, 0.5, 0.5);

    CGContextTranslateCTM(ctx, 0, 150);

    

    CGContextAddRect(ctx, CGRectMake(10, 10, 50, 50));

    CGContextStrokePath(ctx);

    

    CGContextRestoreGState(ctx);

    

    CGContextAddEllipseInRect(ctx, CGRectMake(100, 100, 100, 100));

    CGContextMoveToPoint(ctx, 100, 100);

    CGContextAddLineToPoint(ctx, 200, 250);

    

    // 矩阵操作

    //    CGContextScaleCTM(ctx, 0.5, 0.5);

    

    CGContextStrokePath(ctx);

}

 

/**

 *  裁剪操作

 */

void clipCirle()

{

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    CGContextSaveGState(ctx);

    

    // 0.画圆

    CGContextAddEllipseInRect(ctx, CGRectMake(100, 100, 50, 50));

    // 裁剪

    CGContextClip(ctx);

    CGContextFillPath(ctx);

    

    // 1.显示图片

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

    [image drawAtPoint:CGPointMake(100, 100)];

    

    CGContextRestoreGState(ctx);

    

    CGContextAddRect(ctx, CGRectMake(0, 0, 50, 50));

    CGContextFillPath(ctx);

}

 

/**

 *  重绘(刷帧)

 */

- (void)reDrawCircle

{

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    

    CGContextAddArc(ctx, 125, 125, self.radius, 0, M_PI * 2, 0);

    

    CGContextFillPath(ctx);

}

 

/**

 *  画出下雪的动画

 */

- (void)drawSnowAnimation

{

    // 调用的比较频繁用 CADisplayLink @selector 调用系统自带的方法就够不要自己写

    CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(setNeedsDisplay)];

    [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

    

    // 这个是用定时器调用

//    [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(setNeedsDisplay) userInfo:nil repeats:YES];

    

    self.snowY+=5;

    

    if (self.snowY >= self.frame.size.height) {

        self.snowY = -100;

    }

    

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

    [image drawAtPoint:CGPointMake(0, self.snowY)];

}

 

 

#pragma mark ---- 那么在这里最后也给同学们推荐一个Quartz 2D绘图的博客写的更加详细 有同学需要做K线图\绘图\制表的可以借鉴

// http://donbe.blog.163.com

 

@end

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值