文档章节

iOS——Quartz2D(二维图形绘制)

kinglin_fu
 kinglin_fu
发布于 2016/01/25 17:36
字数 1895
阅读 209
收藏 1

###1、Quartz2D 基本概述

  • Core Graphics Framework是一套基于C的API框架,使用了Quartz作为绘图引擎。它提供了低级别、轻量级、高保真度的2D渲染。

  • Quartz 2D是一个二维图形绘制引擎,适用于iOS和Mac OS X环境,Quartz 2D API可以很多绘制功能,如基本路径的绘制、透明度、描影、绘制阴影、透明层、颜色管理、反锯齿、PDF文档生成。

  • 绘图上下文Graphics Context是一个数据类型(CGContextRef),用于封装Quartz绘制图像到输出设备的信息。 Quartz中所有的对象都是绘制到一个Graphics Context中。用Quartz绘图时,可以简单地给Quartz绘图序列指定不同的Graphics Context,就可将相同的图像绘制到不同的设备上。我们不需要任何设备相关的计算,这些都由Quartz替我们完成。

  • Graphics Context定义了基本的绘制属性,如颜色、裁减区域、线条宽度和样式信息、字体信息、混合模式等。

###2、绘图方法 在iOS应用程序中,如果要使用 Core Graphics 在屏幕上进行绘制图像需要在如下方法中进行。

  • drawRect:方法 需要创建一个UIView对象,并实现它的drawRect:方法。视图的drawRect:方法在视图显示在屏幕上及它的内容需要更新时被调用,或者使用**setNeedsDisplay**手动调用。
// 1. 将自定义视图添加到视图上显示
- (void)viewDidLoad {
    [super viewDidLoad];
    
    DrawView *drawView = [[DrawView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:drawView];
}
// 2. 在自定义的DrawView 中绘图,当视图显示时就会调用下面的代码。
- (void)drawRect:(CGRect)rect
{

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextAddRect(ctx, CGRectMake(10, 20, 100, 100));
    CGContextSetFillColorWithColor(ctx, [UIColor grayColor].CGColor);
    CGContextDrawPath(ctx, kCGPathFill);
}
  • drawLayer: inContext:方法 这是CALayer的代理方法,需要设置图层的代理对象并使用**setNeedsDisplay**方法才能触发这个方法。
// 1.创建一个layer并设置代理为当前控制器
- (void)viewDidLoad {
    [super viewDidLoad]; 
    
    CALayer *dLayer = [CALayer layer];
    dLayer.frame = self.view.bounds;
    dLayer.delegate = self;
    [self.view.layer addSublayer:dLayer];  
    [dLayer setNeedsDisplay]; // 调用这个方法才能触发代理方法绘图
}
// 2. 在代理方法中绘图
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{

	// 绘制三角形
    CGContextSetLineWidth(ctx, 2);
    CGContextSetFillColorWithColor(ctx, [UIColor redColor].CGColor);
    CGContextSetStrokeColorWithColor(ctx, [UIColor whiteColor].CGColor);
    CGContextMoveToPoint(ctx, 0, 400);
    CGContextAddLineToPoint(ctx, 320, 400);
    CGContextAddLineToPoint(ctx, 160, 560);
    CGContextAddLineToPoint(ctx, 0, 400);
    CGContextFillPath(ctx);  // 填充
    CGContextStrokePath(ctx); // 描边
}

###3、Core Graphics上下文函数

  • 绘图上下文相关函数

    UIGraphicsGetCurrentContext(): 获取当前绘图上下文,绘图前的第一步,因为所有的绘图都是在上下文完成的,可以理解为获取当前绘图的“画布”。

    CGContextSaveGState(): 保存上下文状态,这个函数的作用是将当前图形状态推入堆栈。之后,您对图形状态所做的修改会影响随后的描画操作,但不影响存储在堆栈中的拷贝。

    CGContextRestoreGState(): 恢复上下文状态,通过这个函数把堆栈顶部的状态弹出,返回到之前的图形状态。和CGContextSaveGState()配对使用。

    CGContextSaveGState()和CGContextRestoreGState()使用举例:整个绘图都是红色,但是中间需要有个图是灰色,这种场景就可以使用这两个函数处理了。

    	// 先设置图形的填充颜色为红色
    	CGContextSetFillColorWithColor(ctx, [UIColor redColor].CGColor);
    	// 将之前设置的状态入栈保存
    	CGContextSaveGState(ctx); 
    	CGContextAddRect(ctx, CGRectMake(10, 20, 100, 100));
    	// 设置中间图形的填充色修改为灰色
    	CGContextSetFillColorWithColor(ctx, [UIColor grayColor].CGColor);
    	CGContextDrawPath(ctx, kCGPathFillStroke);
    	// 恢复到保存前的绘图状态,那么后面的绘图就不是灰色了,而是原来的红色。
    	CGContextRestoreGState(ctx); 
    
  • 绘图路径相关函数

    CGContextMoveToPoint(): 定位到某个点

    CGContextAddLineToPoint(): 画线,添加一条直线到一个点

    CGContextAddRect(): 画矩形

    CGContextAddEllipseInRect(): 内切圆或者椭圆

    CGContextAddQuadCurveToPoint(): 一个控制点的贝塞尔曲线

    CGContextAddCurveToPoint(): 两个控制点的贝塞尔曲线

    CGContextAddArc(): 画曲线

    CGContextSetLineDash(): 画虚线

    CGContextAddPath(): 画指定的路劲

    CGContextClosePath(): 闭合当前路径

  • 绘图设置相关函数

    CGContextSetLineWidth(): 设置线条的宽度

    CGContextSetStrokeColorWithColor(): 设置线条的颜色(使用UIColor颜色)

    CGContextSetStrokeColor(): 设置线条颜色(三色值和透明度)

    CGContextSetRGBStrokeColor(): 设置线条颜色(RGB值)

    CGContextSetFillColor(): 设置图形填充颜色(三色值和透明度)

    CGContextSetFillColorWithColor(): 设置填充颜色(UIColor值)

    CGContextSetRGBFillColor():设置填充颜色(RGB值)

    CGContextSetAlaha(): 设置透明度

    CGContextSetShouldAntialias(): 是否开启抗锯齿

    CGContextSetLineCap(): 设置直线端点的样式()

    CGContextSetLineJoin(): 设置直线连接点的样式

    CGContextSetShadow(): 设置阴影(尺寸和模糊度)

    CGContextSetShadowWithColor(): 设置阴影和阴影颜色

  • 图形填充相关函数

    CGContextFillRect(): 填充一个矩形

    CGContextStrokePath(): 描边

    CGContextFillPath(): 只填充不描边

    CGContextEOFillPath(): 使用奇偶规则填充

    CGContextDrawPath(): 绘制路径(可以选择填充的样式)

###4、使用Core Graphics绘图

  • 第一步:获取当前绘图上下文,相当于创建“画布”
    CGContextRef ctx = UIGraphicsGetCurrentContext();
  • 第二步:设置要绘制的图形
    //直线
    CGContextMoveToPoint(ctx, 100, 250);
    CGContextAddLineToPoint(ctx, 150, 150);
    // 矩形
    CGContextAddRect(ctx, CGRectMake(10, 20, 100, 100));
    // 内切圆\椭圆
    CGContextAddEllipseInRect(ctx, CGRectMake(120, 20, 100, 100));
    // 三角形
    CGContextMoveToPoint(ctx, 0, 400);
    CGContextAddLineToPoint(ctx, 320, 400);
    CGContextAddLineToPoint(ctx, 160, 560);
    CGContextClosePath(ctx);
    // 一个控制点的贝塞尔曲线
    CGContextAddQuadCurveToPoint(ctx, 80, 100, 160, 300);
```	
// 两个控制点的贝塞尔曲线
CGContextAddCurveToPoint(ctx, 80, 100, 240, 500, 320, 300);
// 弧线
CGContextAddArc(ctx, 240, 200, 80, 0, M_PI_2, NO);
// 绘制图片
CGRect imageFrame = CGRectMake(10, 30, 300, 300);
// 获取图片数据
NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"png"]; 
UIImage *img = [UIImage imageWithContentsOfFile:imagePath];

// 设置上下文当前转换矩阵(CTM),否则图片倒置
CGContextTranslateCTM(context, 0, imageFrame.size.height);
CGContextScaleCTM(context, 1, -1);
CGContextDrawImage(context, imageFrame, img.CGImage); // 绘制
// 或者如下绘制,不需要设置CTM
[img drawInRect:imageFrame];
* 第三步:设置图形的属性(颜色、线条……)

CGContextSetLineWidth(ctx, 5); // 线宽
CGContextSetFillColorWithColor(ctx, [UIColor blueColor].CGColor); // 填充颜色
CGContextSetStrokeColorWithColor(ctx, [UIColor whiteColor].CGColor); // 线条颜色
CGContextSetShouldAntialias(ctx, YES); // 抗锯齿
CGContextSetLineCap(ctx, kCGLineCapRound); // 线头颜色
CGContextSetLineJoin(ctx, kCGLineJoinBevel); // 链接点样式
* 第四步:绘图(填充)

CGContextFillPath(ctx);    // 填充
CGContextStrokePath(ctx); // 描边
// 或者填充并描边 
CGContextDrawPath(ctx, kCGPathFillStroke);

###5、使用UIBezierPath绘图
UIKit中的UIBezierPath是Core Graphics框架关于path的一个封装(封装为OC的方法)。 使用UIBezierPath绘图不需要手动获取绘图上下文,当drawRect方法被调用时,UIView的绘图上下文属于当前图形上下文。

* **实例化一个path对象**

// 不设置图形路径
UIBezierPath *path = [UIBezierPath bezierPath];
// 矩形路径
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(50, 100, 200, 200)];
// 内切圆\椭圆路径
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 100, 200, 200)];
//圆角矩形路径 
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(50, 100, 200, 200) cornerRadius:20];
// 弧线路径,ArcCenter:原点、radius:半径、startAngle:起点弧度、endAngle:终端弧度、clockwise:是否顺时针
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(100, 100) radius:50 startAngle:0 endAngle:M_PI_2 clockwise:YES];

* **添加路径**

// 移动到某个点
[path moveToPoint:p1];

// 添加一条线到某个点
[path addLineToPoint:p2];

// 添加一条贝塞尔曲线
[path addQuadCurveToPoint:p1 controlPoint:p2];

// 添加一条弧线
[path addArcWithCenter:p1 radius:50 startAngle:M_PI_4 endAngle:M_PI_2 clockwise:YES];

// 闭合路径
[path closePath];	

// 移除所有的点
[path removeAllPoints];
* **设置路径属性**

// 设置填充颜色
[[UIColor redColor] setFill]; 

// 设置描边颜色

[[UIColor whiteColor] setStroke];

// 线宽 path.lineWidth = 5;

// 线头样式
path.lineCapStyle = kCGLineCapRound;

// 线连接点样式
path.lineJoinStyle = kCGLineJoinMiter;

// 连接点的斜距(角的内点和外点的距离),连接样式得为kCGLineJoinMiter
path.miterLimit = 20;
* **绘图(填充)**

[path fill];    // 填充
[path stroke];  // 描边
###6、实例Demo下载

下载链接:[https://github.com/fuqinglin/Quartz2DDemos.git](https://github.com/fuqinglin/Quartz2DDemos.git)

© 著作权归作者所有

kinglin_fu
粉丝 16
博文 11
码字总数 14320
作品 0
石景山
私信 提问
iOS 技术提升计划

1.多线程 多线程讲解 2.iOS与H5交互(WKWebView框架) WKWebView API精讲 WKWebView与JS交互 3.缓存机制 内存缓存 设计一个移动应用的本地缓存机制 4.内存优化 UITableView的性能优化 iOS应用性...

zY_Wang
2016/04/01
11
1
iOS之QuartZ 2D 绘图(一)

Quartz2D Quartz2D是苹果封装的一个库,针对iOS和os系统绘制不同的类型的制图方式 图形上下文(一种数据类型,类似int,double)数据类型() 不同的(数据类型)可以绘制不同的类型(,,,,) 进而上面5...

追逐iOS
05/21
0
0
iPhone之Quartz 2D系列--图形上下文(2)Graphics Contexts

以下几遍关于Quartz 2D博文都是转载自:http://www.cocoachina.com/bbs/u.php?action=topic&uid=38018 有关本章博客的代码实现,大家可以参考我的这遍博客:IOS用CGContextRef画各种图形(文字...

长平狐
2013/12/25
62
0
iOS开发系列--打造自己的“美图秀秀”

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jianxin160/article/details/47753221 --绘图与滤镜全面解析 概述 在iOS中可以很容易的开发出绚丽的界面效果,...

KenshinCui
2015/08/18
0
0
疯狂iOS讲义之在内存中绘图

前面介绍的都是通过扩展UIView、重写drawRect:方法进行绘图,这种绘图方式是直接在UIView控件上绘制所有的图形——由于每次该控件显示出来时,drawRect:方法都会被调用,这意味着每次该控件显...

博文视点
2014/02/11
2.9K
1

没有更多内容

加载失败,请刷新页面

加载更多

idea下springboot 项目在static目录下添加文件不生效

idea下springboot 项目在static目录下添加文件不生效 问题描述 是这样子的,我的项目目录结构如下: 我在static目录下,创建了index.html和aaaa.jpg这两个文件。然后,启动服务访问 http://l...

wotrd
昨天
5
0
k8s1.14 一、环境

1. 4台虚拟机 (CentOS Linux release 7.2.1511 (Core) ) 192.168.130.211 master 192.168.130.212 node1 192.168.130.213 node2 192.168.130.214 node3 2. 设置服务器hostname 2.1 设置本机......

ThomasCheng
昨天
4
0
盖茨:如果我现在开创一家公司 将会专注于AI

新浪科技讯,北京时间 6 月 26 日凌晨消息,微软联合创始人比尔·盖茨(Bill Gates)在周一接受采访时表示,如果他今天从哈佛大学辍学并开创一家新公司,那么这家公司将会专注于人工智能(A...

linuxCool
昨天
1
0
聊聊feign的Retryer

序 本文主要研究一下feign的Retryer Retryer feign-core-10.2.3-sources.jar!/feign/Retryer.java public interface Retryer extends Cloneable { /** * if retry is permitted, retur......

go4it
昨天
12
0
HyperLogLog简介

  (1)HyperLogLog简介      在Redis 在 2.8.9 版本才添加了 HyperLogLog,HyperLogLog算法是用于基数统计的算法,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个...

SEOwhywhy
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部