CGPattern是在图形上下文中重复绘制的一系列绘制操作。你可以像使用颜色一样使用图案。当使用CGPattern进行绘制时,Quartz将页面划分为一组图案单元格,每个单元格的大小为CGPattern初始化时bounds的大小,并使用您提供的回调来绘制每个单元格。下图为一个简单的CGPattern绘制的图案:

白色部分为图形绘制的上下文 ,带蓝色边框的区域为CGPattern绘制的单元格,它是根据指定规则平铺在图形上下文中的。它总是从上下文的左上角(坐标系原点为左上角时)开始绘制,然后按照一定规则平铺满整个图形上下文。

上面图案的绘制具体代码如下:

  1. override func draw(_ rect: CGRect) {
  2. guard let context = UIGraphicsGetCurrentContext() else { return }
  3.  
  4. context.saveGState() // 保存上下文状态,以便绘制完图案后恢复上下文原来的状态(即:这里保存之前的状态)
  5.  
  6. // 初始化一个回调函数
  7. // 参数
  8. // 1:版本号,一般传0即可;
  9. // 2:一个绘制图案的函数(该函数有两个参数,1:CGPattern初始化时第一个参数info;2:绘制图案的上下文)
  10. // 3:释放CGPattern初始化时第一个参数info指针的回调函数
  11. var callbacks = CGPatternCallbacks(version: 0, drawPattern: { (info, ctx) in
  12.  
  13. // 这里获取CGPattern初始化时传入的图案单元格的size(注意:这里不能用takeRetainedValue(),这样会导致info资源回收,而在下次回调中报错)
  14. let size = Unmanaged<NSValue>.fromOpaque(info!).takeUnretainedValue().cgSizeValue
  15. let bounds = CGRect(origin: .zero, size: size)
  16. // 设置画笔宽度
  17. ctx.setLineWidth(2)
  18. // 设置画笔颜色
  19. ctx.setStrokeColor(UIColor.red.cgColor)
  20. // 设置填充色
  21. ctx.setFillColor(UIColor.green.cgColor)
  22. // 添加一个矩形框
  23. ctx.addRect(bounds)
  24. // 绘制边框并填充颜色
  25. ctx.drawPath(using: .fillStroke)
  26. }) { info in
  27. // 需要在这里将CGPattern初始化时传入info指针内存回收
  28. Unmanaged<NSValue>.fromOpaque(info!).release()
  29. }
  30.  
  31. // 图案单元格的间隙
  32. let space: CGFloat = 10
  33. // 当前上下文中,水平方向上单元格的个数(用于计算单元格的size)
  34. let cellCount: CGFloat = 5
  35. let drawBounds = bounds // 当前上下文画布矩形
  36. // 计算图案单元格尺寸
  37. let cellSize = (drawBounds.width - space * (cellCount - 1)) / cellCount
  38. let size = CGSize(width: cellSize, height: cellSize)
  39. // 初始化CGPattern
  40. // 参数
  41. // 1:用于向绘制函数中传递的info,这里我们将图案的单元格size作为info(这里使用passRetained,是为了保持NSValue的引用计数)
  42. // 2:设置图案单元格的尺寸
  43. // 3:突然单元格的变换矩阵
  44. // 4:单元格水平方向的间距
  45. // 5:单元格垂直方向的间距
  46. // 6:平铺模式
  47. // 7:图案单元格是否为彩色的(当我们绘制的突然需要颜色时,设置为true)
  48. // 8:绘制图案的回调
  49. guard let pattern = CGPattern(info: Unmanaged<NSValue>.passRetained(NSValue(cgSize: size)).toOpaque(),
  50. bounds: CGRect(x: 0, y: 0, width: size.width, height: size.height),
  51. matrix: .identity,
  52. xStep: size.width + space,
  53. yStep: size.height + space,
  54. tiling: .noDistortion,
  55. isColored: true,
  56. callbacks: &callbacks) else {
  57. print("pattern create fail")
  58. return
  59. }
  60. // 创建颜色空间,采用patternBaseSpace初始化(注意:如果isColored=true,这里一般设置为nil即可)
  61. guard let colorSpace = CGColorSpace(patternBaseSpace: nil) else {
  62. print("colorSpace create fail")
  63. return
  64. }
  65. // 设置填充的颜色空间(这里必须设置,否则图案将无法正常绘制填充色)
  66. context.setFillColorSpace(colorSpace)
  67. var alpha: CGFloat = 1
  68. // 设置填充图案CGPattern,用于填充绘制。第二个参数:指定了图案绘制中用到的颜色透明度
  69. context.setFillPattern(pattern, colorComponents: &alpha)
  70. // 调用填充绘制,这里会采用上面的pattern进行绘制
  71. context.fill(drawBounds)
  72. context.restoreGState() // 恢复上下文状态
  73. }

具体细节已在代码注释中说明,但是这里我要着重说明一下xStep和yStep这两个参数。我们用一张图来理解一下:

从图中可知,xStep是距离前一个图案单元格水平原点的距离,yStep是距离前一个图案单元格垂直原点的距离。因此,如果xStep小于单元格的宽度,那么前后两个单元格在水平方向将会重叠,yStep同样如此。

我们可以在回调函数中任意绘制我们的图案,不局限在绘制矩形或线条,向下面这样:

下面是具体绘制的部分代码:

  1. var callbacks = CGPatternCallbacks(version: 0, drawPattern: { (info, ctx) in
  2.  
  3. // 这里获取CGPattern初始化时传入的图案单元格的size(注意:这里不能用takeRetainedValue(),这样会导致info资源回收,而在下次回调中报错)
  4. let size = Unmanaged<NSValue>.fromOpaque(info!).takeUnretainedValue().cgSizeValue
  5.  
  6. // 设置填充色
  7. ctx.setFillColor(UIColor.red.cgColor)
  8.  
  9. let psize = min(size.width, size.height)
  10. var r: Double, theta: Double
  11. r = 0.8 * psize / 2
  12. theta = 2 * Double.pi * (2.0 / 5.0)
  13. ctx.translateBy(x: psize/2, y: psize/2)
  14. ctx.move(to: .init(x: 0, y: r))
  15. for k in 1..<5 {
  16. ctx.addLine(to: .init(x: r * sin(Double(k) * theta), y: r * cos(Double(k) * theta)))
  17. }
  18. ctx.closePath()
  19. ctx.fillPath()
  20. }) { info in
  21. // 需要在这里将CGPattern初始化时传入info指针内存回收
  22. Unmanaged<NSValue>.fromOpaque(info!).release()
  23. }

Quartz 2D CGPattern学习笔记的更多相关文章

  1. Quartz 2D编程指南(1) - 概览

    Quartz 2D编程指南是论坛会员德鲁伊翻译的国外的Quartz 2D一系列学习资料,供大家参考 Quartz 2D是一个二维图形绘制引擎,支持iOS环境和Mac OS X环境.我们可以使用Quar ...

  2. Quartz学习笔记:集群部署&高可用

    Quartz学习笔记:集群部署&高可用 集群部署 一个Quartz集群中的每个节点是一个独立的Quartz应用,它又管理着其他的节点.这就意味着你必须对每个节点分别启动或停止.Quartz集群 ...

  3. Quartz学习笔记:基础知识

    Quartz学习笔记:基础知识 引入Quartz 关于任务调度 关于任务调度,Java.util.Timer是最简单的一种实现任务调度的方法,简单的使用如下: import java.util.Tim ...

  4. 我的Android进阶之旅------>Android中编解码学习笔记

    编解码学习笔记(一):基本概念 媒体业务是网络的主要业务之间.尤其移动互联网业务的兴起,在运营商和应用开发商中,媒体业务份量极重,其中媒体的编解码服务涉及需求分析.应用开发.释放license收费等等 ...

  5. NGUI学习笔记(一)UILabel介绍

    来个前言: 作为一个U3D程序员,自然要写一写U3D相关的内容了.想来想去还是从UI开始搞起,可能这也是最直观同时也最重要的部分之一了.U3D自带的UI系统,也许略坑,也没有太多介绍的价值,那么从今天 ...

  6. Theano 学习笔记(一)

    Theano 学习笔记(一) theano 为什么要定义共享变量? 定义共享变量的原因在于GPU的使用,如果不定义共享的话,那么当GPU调用这些变量时,遇到一次就要调用一次,这样就会花费大量时间在数据 ...

  7. html5学习笔记一

    HTML5学习笔记 <video>标记:定义视频,Ogg.MPEG4.WebM三种格式 <video src=”movie.ogg”  controls=”controls”> ...

  8. iOS 2D绘图 (Quartz 2D) 概述

    本篇博客原文地址:http://blog.csdn.net/hello_hwc?viewmode=list 由于自己的项目需要,从网络上下载了许多关于绘制图形的demo,只是用在自己的项目中,很多地方 ...

  9. Android动画学习笔记-Android Animation

    Android动画学习笔记-Android Animation   3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中 ...

  10. opencv学习笔记(三)基本数据类型

    opencv学习笔记(三)基本数据类型 类:DataType 将C++数据类型转换为对应的opencv数据类型 OpenCV原始数据类型的特征模版.OpenCV的原始数据类型包括unsigned ch ...

随机推荐

  1. mysql16 sql优化-order by-GROUP BY

    1.简要说明   在sql中常常用到order by,排序对于sql的查询速度有较大的的影响.mysql支持两种排序方式,FileSort和Index,Index效率高,它指MySQL扫描索引本身完成 ...

  2. 后台管理系统带关闭的选项卡(多标签页)功能 适配bootstrap3和4 Bootstrap Hover Dropdown

    眼看着是不是很熟悉,其实基本大部门后台管理系统都有这个功能,使用iframe实现展示标签页面. 主要功能:标签页点击,添加标签页,向左滚动标签页,向右滚动标签页,刷新当前标签页,关闭当前标签页,关闭其 ...

  3. Spring(IOC自动装配-基于注解开发)

    Spring IoC 自动装载 autowire: 自动装载是Spring提供的一种更加简单的方式,来完成DI,不需要手动配置property ,IoC容器会自动选择Bean玩成注入. 自动装载俩种: ...

  4. StatefulWidget 组件的参数时(widget.xxx)报 Invalid Constant Value

    一个 Flutter 组件(Widget)在很多情况下都需要接收一些参数.Flutter 插件通常提示使用 const 关键字包裹某 Widget(很多人接受建议且执行),导致通过 widget.xx ...

  5. torch.nn.Embedding使用详解

    torch.nn.Embedding: 随机初始化词向量,词向量值在正态分布N(0,1)中随机取值.输入:torch.nn.Embedding(num_embeddings, – 词典的大小尺寸,比如 ...

  6. openssl国密算法库

    openssl国密算法库 一.开发背景 openssl是一个功能丰富且自包含的开源安全工具箱.它提供的主要功能有:SSL协议实现(包括SSLv2.SSLv3和TLSv1).大量软算法(对称/非对称/摘 ...

  7. k8s-分布式系统架构master-worker

    K8S系列一:概念入门 - 知乎 (zhihu.com) 大白话先了解k8s. k8s是为容器服务而生的一个可移植容器的编排管理工具 概述 Master-Workers 架构(粗译为主从架构)是分布式 ...

  8. selenium用executeAsyncScript执行异步脚本调用callback使用方法

    executeAsyncScript的作用: 就是把异步的js过程变成java同步的形式,方便java程序及时的接收到同步数据 1.cmdriver.manage().timeouts().scrip ...

  9. JetBrains之全家桶破解

    JetBrains之全家桶破解(idea,rider....) 链接之....JETBRA.IN 打开上面的链接 随便点击下图中一个可用的链接,进入之后看下一步. 打开上一步的链接之后,下载下图中红框 ...

  10. ant design vue datePicker 日期时间范围设置默认为当天0点-23点59

    <template> <a-card :bordered="false"> <a-range-picker show-time :default-va ...