Core Graphics快速入门——从一行代码说起

Core Graphics入门

想必每个第一次接触Core Graphics的开发者都被无数的API、混乱的代码逻辑折腾得头疼不已,甚至望而却步。即使是绘制一个简单的矩形也看上去非常繁琐。本文换一个角度,整理一下有关Core Graphics的知识,也算作是这段时间学习的总结。

Core Graphics和UIKit的区别

首先从概念上了解一下:

根据苹果的描述,UIKit是我们最容易也是最常接触到的框架。绝大多数图形界面都由UIKit完成。但是UIKit依赖于Core Graphics框架,也是基于Core Graphics框架实现的。如果想要完成某些更底层的功能或者追求极致的性能,那么依然推荐使用Core Graphics完成。

Core Graphics和UIKit在实际使用中也存在以下这些差异:

  1. Core Graphics其实是一套基于C的API框架,使用了Quartz作为绘图引擎。这也就意味着Core Graphics不是面向对象的。
  2. Core Graphics需要一个图形上下文(Context)。所谓的图形上下文(Context),说白了就是一张画布。这一点非常容易理解,Core Graphics提供了一系列绘图API,自然需要指定在哪里画图。因此很多API都需要一个上下文(Context)参数。
  3. Core Graphics的图形上下文(Context)是堆栈式的。只能在栈顶的上下文(画布)上画图。
  4. Core Graphics中有一些API,名称不同却有着相似的功能,新手只需要掌握一种,并能够看懂其他的即可。

从一行代码说起

下面这行代码应该是很多人最早也是最常写的代码。它简单到我们根本不用思考它的本质。

[self.view addSubview:myButton];

细想一下,UIButton也是继承自UIView。这段代码表示,UIKit绘图的基本思想是通过UIView的叠加实现最终的整体效果。它主要涉及三个内容:画布、被添加的控件和添加方法。这里的self.view其实就充当了一张画布。通过添加不同的UI控件达到最终效果。我们顺着这个线索整理一下Core Graphics的编程思路。

Core Graphics的基本使用

为了使用Core Graphics来绘图,最简单的方法就是自定义一个类继承自UIView,并重写子类的drawRect方法。在这个方法中绘制图形。

Core Graphics必须一个画布,才能把东西画在这个画布上。在drawRect方法方法中,我们可以直接获取当前栈顶的上下文(Context)。下面的代码演示了具体操作步骤:

- (void)drawRect:(CGRect)rect {
    CGContextRef ctx = UIGraphicsGetCurrentContext();
}

现在我们已经完成了Core Graphics绘图的三分之一——创建一个画布。

接下来需要考虑被画上去的东西。这在UIKit中往往是一个UI控件,如Button、Label等。而在Core Graphics中通常表现为一些基本图形:三角形、矩形、圆形、以及这些图形的边框等。

这通常会涉及到非常多的API,但是如果总结一下不难发现,任何一个要绘制的东西(为了避免混淆就不称为对象了)一定有一个边框,或者称为边界。在一个几英寸的屏幕上画出无界的图形是不可能的。所以一旦确定了一个边框,我们就可以设置边框的各种绘图属性、边框内部区域的绘图属性、绘制边框还是内部区域等。

这就引出了Core Graphics中的路径(Path)的概念。在前一段代码的基础上演示路径的使用:

- (void)drawSomething{
    CGContextRef context = UIGraphicsGetCurrentContext();//获取上下文
    CGMutablePathRef path = CGPathCreateMutable();//创建路径
    CGPathMoveToPoint(path, nil, 20, 50);//移动到指定位置(设置路径起点)
    CGPathAddLineToPoint(path, nil, 20, 100);//绘制直线(从起始位置开始)
    CGContextAddPath(context, path);//把路径添加到上下文(画布)中
}

这里通过CGPathCreateMutable方法创建了一个路径。路径的外在表现就像一条折线。为了绘制一条路径,需要用CGPathMoveToPoint函数指定路径的起点。CGPathAddLineToPoint函数表示在路径的最后结束点和新的点之间再加一条直线。相当于拓展了原来路径。通过这样的简单的点的累加,可以绘制非常复杂的折线。

但这存在两个问题:

  1. 绘制矩形等规则多边形的过程过于繁琐
  2. 无法绘制曲线。

这些问题Core Graphics早已提供了解决办法。注意到之前我们添加了一个非常普通的自定义路径。Core Graphics中还提供了很多预先设置好的路径。不妨在drawRect方法中输入“cgcontextadd”试试看。

这些方法由Core Graphics提供,可以用来绘制圆形、椭圆、矩形、二次曲线等路径。创建完路径后还要记得调用CGContextAddPath方法将路径添加到上下文中。路径只是我们画的一条线而已,不把他画到上,他就没有什么卵用。

添加好路径后,就要开始画图了。正如前面提出的问题所说,画图的时候需要考虑画不画边框、画不画边框内部的区域,边框的粗细、颜色、内部区域颜色等问题。Core Graphics提供了另一个方法集合”CGContextSet”来进行这些设置。常见的设置内容如下:

- (void)drawSomething{
    CGContextRef context = UIGraphicsGetCurrentContext();//获取上下文
    CGMutablePathRef path = CGPathCreateMutable();//创建路径
    CGPathMoveToPoint(path, nil, 20, 50);//移动到指定位置(设置路径起点)
    CGPathAddLineToPoint(path, nil, 20, 100);//绘制直线(从起始位置开始)
    CGContextAddPath(context, path);//把路径添加到上下文(画布)中

    //设置图形上下文状态属性
    CGContextSetRGBStrokeColor(context, 1.0, 0, 0, 1);//设置笔触颜色
    CGContextSetRGBFillColor(context, 0, 1.0, 0, 1);//设置填充色
    CGContextSetLineWidth(context, 2.0);//设置线条宽度
    CGContextSetLineCap(context, kCGLineCapRound);//设置顶点样式
    CGContextSetLineJoin(context, kCGLineJoinRound);//设置连接点样式
    CGFloat lengths[2] = { 18, 9 };
    CGContextSetLineDash(context, 0, lengths, 2);
    CGContextSetShadowWithColor(context, CGSizeMake(2, 2), 0, [UIColor blackColor].CGColor);
    CGContextDrawPath(context, kCGPathFillStroke);//最后一个参数是填充类型
}

设置属性的前三行就不再解释了,看一些注释足矣。顶点指的是路径的起始点和结束点,连接点指的是路径中的转折点(折现才有)。SetLineDash用于绘制虚线,具体用法参见——《IOS中使用Quartz 2D绘制虚线》。SetShadow方法用于绘制阴影,第二个参数是一个CGSize对象,用于表示阴影偏移量,第三个参数表示模糊度,数值越大,阴影越模糊,第一个参数是一个CGColor,表示阴影颜色,需要由UIColor转换得到。

至此,我们完成了Core Graphics绘图的第二步,也是最复杂的一部分:设置绘图内容。这相当于此前那行代码的中的UI控件。

设置好了绘图的属性之后,就可以调用CGContextDrawPath方法绘图了。第一个参数表示要在哪一个上下文中绘图,第二个参数表示填充类型。在填充类型中可以选择只绘制边框、只填充、同时绘制边框和填充内部区域、奇偶规则填充等。

从方法名不难看出,但是也需要注意的是,这些设置都是对上下文(context)生效的。这样会导致,所有的边框颜色、粗细都一样。一个简单的解决办法就是在需要修改设置之前调用一次CGContextDrawPath方法绘图。再修改设置,修改设置之后再次绘制。

图画完了,还得做一下清理工作。CGPathCreateMutable方法返回的路径是一个Core Fundation Object。而这并不在ARC的管理范围之内。所以需要手动释放对象。

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();//获取上下文
    CGMutablePathRef path = CGPathCreateMutable();//创建路径
    /*
        绘图
    */
    CGPathRelease(path);
}

这样就完成了Core Graphics绘图的第三部分——开始绘图。

再总结一下使用Core Graphics绘图的步骤:

  1. 获取上下文(画布)
  2. 创建路径(自定义或者调用系统的API)并添加到上下文中。
  3. 进行绘图内容的设置(画笔颜色、粗细、填充区域颜色、阴影、连接点形状等)
  4. 开始绘图(CGContextDrawPath)
  5. 释放路径(CGPathRelease)
时间: 2024-10-24 12:35:48

Core Graphics快速入门——从一行代码说起的相关文章

Java中23种设计模式--超快速入门及举例代码

在网上看了一些设计模式的文章后,感觉还是印象不太深刻,决定好好记录记录. 原文地址:http://blog.csdn.net/doymm2008/article/details/13288067 注:本文代码基本都有很多没有初始化等等问题,主要是为了减少代码量,达到一眼就能了解大概情况的目的. java的设计模式大体上分为三大类: 创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式. 结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,

JavaWeb快速入门Session&Cookie代码思路篇(七)

Cookie练习 简介 尝试了n种分享代码,最终没有找到好办法.我觉得贴代码,很难看下去.还不如写思路,今后代码篇改成思路篇 Session代码练习 1. 购物车思路 1. ListBookServlet类 1.1 显示该网站所有商品,每个商品加上购买链接(BuyServlet) 用Map集合存储Book对象 map.put("1", new Book("1","JavaWeb开发","老张","一本好书"

.NET Core实战项目之CMS 第二章 入门篇-快速入门ASP.NET Core看这篇就够了

作者:依乐祝 原文链接:https://www.cnblogs.com/yilezhu/p/9985451.html 本来这篇只是想简单介绍下ASP.NET Core MVC项目的(毕竟要照顾到很多新手朋友),但是转念一想不如来点猛的(考虑到急性子的朋友),让你通过本文的学习就能快速的入门ASP.NET Core.既然是快速入门所以过多过深的内容我这里就一笔带过了!然后在后面的一些列文章中再慢慢的对其中的概念进行阐述. 本文已收录至.NET Core实战项目之CMS 第一章 入门篇-开篇及总体规

.Net Core 3.0 IdentityServer4 快速入门

原文:.Net Core 3.0 IdentityServer4 快速入门 .Net Core 3.0 IdentityServer4 快速入门 一.简介 IdentityServer4是用于ASP.NET Core的OpenID Connect和OAuth 2.0框架. 将IdentityServer4部署到您的应用中具备如下特点: 1).认证服务 2).单点登陆 3).API访问控制 4).联合网关 5).专注于定制 6).成熟的开源系统 7).免费和商业支持 二.整体部署 目前大多数的应用

数据库快速入门例子代码

数据库快速入门例子代码 下面的内容将简单说明怎样使用数据库.更详细的信息请阅读各个函数的单独介绍页面. 初始化数据库类 下面的代码将依据你的数据库配置载入并初始化数据库类: $this->load->database(); 一旦被载入,你可以在任何地方像这样使用它: 注意: 如果你的所有页面均要求初始化数据库类,你可以让它自动加载.详见 数据库连接. 多结果标准查询(对象形式) $query = $this->db->query('SELECT name, title, email

一行代码,快速为UITableView创建Delegate和DataSource

只需一行代码,快速为UITableView创建Delegate和DataSource. 简介CBTableViewDataSource是一个轻量级的用于快速创建UITableView的DataSource和Delegate的框架.它提供了一些方便的API,帮助用户以一种快速和有逻辑的方式创建DataSource和Delegate. 最偷懒的使用方式如下:[_tableView cb_makeSectionWithData:self.viewModel.data andCellClass:[Cus

【ASP.NET Core快速入门】(二)部署到IIS

原文:[ASP.NET Core快速入门](二)部署到IIS 配置IIS模块 ASP.NET Core Module载地址:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/aspnet-core-module?tabs=aspnetcore2x 安装后再IIS管理器模块页面会出现aspnetcoremodule 新建网站 修改应用池 网站发布 控制台方式 dotnet publish发布到项目文件的bin/deb

.Net Core 3.0 IdentityServer4 快速入门02

.Net Core 3.0 IdentityServer4 快速入门 —— resource owner password credentials(密码模式) 一.前言 OAuth2.0默认有四种授权模式(GrantType): 1)授权码模式 2)简化模式 3)密码模式(resource owner password credentials) 4)客户端模式(client_credentials) 上一小节接受了 客户端模式 ,本小节将介绍 密码模式,OAuth2.0资源所有者密码授权功能允许

快速开发框架(FDMS)新增1000个对外接口都不须要手写一行代码

一个大型系统难免会跟其它系统有数据交换,这里就要提供数据接口给外部系统. 曾经在一家智能终端设备的公司上班.那段时间的主要工作就是写接口.接口须要与手机.手持设备.系统管理软件等进行数据交换.总结了一下大部分时间都在做重复的工作. 于是我想到可不可以做出一个接口模型来,具体的数据交换怎么实现由用户来定义,那样的话就算要加1000个接口我都不用写一行代码. 看一下下面的图片 一般的操作直接选择普通操作类型即可. 复杂一点的操作可以选择存储过程来处理. 定义完接口以后,调用接口的时候可以按XML,J