1. 概述

本专栏之前的文章讲述了CALayer的使用以及一些动画操作等,本篇文章主要对CALayer的一些专用图层CAShapeLayer、CATextLayer、CATransformLayer进行讲解。

2. CAShapeLayer

A layer that draws a cubic Bezier spline in its coordinate space.

class CAShapeLayer : CALayer

CAShapeLayer是一个通过矢量图形而不是bitmap来绘制的图层子类,我们可以指定线宽、颜色等属性,用CGPath来绘制想要的图层,最后CAShapeLayer就自动渲染出来了。除了这种方法,我们也可以通过Core Graphics向原始Layer直接绘制一个路径,不过相比之下,CAShapeLayer有以下有点:

  • 渲染速度快。CAShapeLayer使用了硬件加速,绘制同一个图形会比Core Graphics快很多。
  • 高效使用内存。一个CAShapeLayer不需要像普通的Layer一样创建一个寄宿图形,所以无论多大,都不会占用太多的内存。
  • 不会被图层边界裁剪。 一个 CAShapeLayer 可以在边界之外绘制。
  • 不会出现像素化。当给CAShapeLayer做3D变换时,它不像一个有寄宿图的普通图层一样变得像素化。
下面看一下CAShapeLayer常用的属性:
属性 类型 说明
path CGPath?  所绘制图形的路径。
fillColor CGColor? 图形填充颜色。
fillRule CAShapeLayerFillRule

填充规则。

nonZero: 默认值。非零规则。将每个从左到右的路径计数为+1,每个从右到左的路径计数为-1。如果所有交点的和为0,则该点在路径外。如果和是非零的,那么点就在路径内,并且包含它的区域被填充。

evenOdd: 奇偶规则。计算穿越路径的总数。如果交叉点的数量是偶数,则该点在路径外。如果交叉数为奇数,则该点位于路径内,并且应该填充包含该点的区域。

lineCap CAShapeLayerLineCap

指定边线端点的形状。buttroundsquare。其中butt为默认值。

lineDashPattern [NSNumber]?

设置边线的样式,默认为实现,可设置为虚线。

例如如果是[2,3],那么绘制规则为绘制2个单元的实线,然后3个单元不绘制,周而复始。

如果是[10,5,5,5],那么绘制10个单元实线,5个单元不绘制,再绘制5个单元实现,5个单元不绘制,周而复始。

lineDashPhase CGFloat 边线样式的起始位置,即,如果lineDashPattern设置为@[2,2,3,4],lineDashPhase即为第一个长度为2的线的起始位置。
lineJoin CAShapeLayerLineJoin

边线拐点处的样式。miter, round, bevel。默认为miter。

lineWidth CGFloat 设置边线宽度。
strokeColor CGColor? 设置边线颜色。

在了解了CAShapeLayer的常用属性后,就来用一下吧:

    func shaperLayerTest() {let width: CGFloat = UIScreen.main.bounds.size.widthlet height: CGFloat = widthlet shapeLayer = CAShapeLayer()shapeLayer.frame = CGRect(x: 0, y: 100, width: width, height: height)let path = CGMutablePath()stride(from: 0, to: CGFloat.pi * 2, by: CGFloat.pi / 6).forEach {angle invar transform  = CGAffineTransform(rotationAngle: angle).concatenating(CGAffineTransform(translationX: width / 2, y: height / 2))let petal = CGPath(ellipseIn: CGRect(x: -20, y: 0, width: 40, height: 100),transform: &transform)path.addPath(petal)}shapeLayer.path = pathshapeLayer.strokeColor = UIColor.red.cgColorshapeLayer.fillColor = UIColor.yellow.cgColorshapeLayer.fillRule = .evenOddself.view.layer.addSublayer(shapeLayer)}

执行效果如下:

除了上面的用法,还有一个需要提一下,那就是圆角

CALayer给圆角提供了一个属性cornerRadius,这个属性支持四个角同时改成圆角。这个属性很方便,但是如果只想针对某一个角进行倒角呢?

采用CAShapeLayer可以指定某一个角进行倒圆角,虽然代码有些多,但还是值得一用的。

参考代码如下:

    func roundCorner() {let rect = CGRect(x: 30, y: 100, width: 150, height: 150)let raddi = CGSize(width: 20, height: 20)let corners: UIRectCorner = [.bottomLeft, .bottomRight]let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: raddi)let shapeLayer = CAShapeLayer()shapeLayer.path = path.cgPathshapeLayer.strokeColor = UIColor.red.cgColorshapeLayer.fillColor = UIColor.clear.cgColorshapeLayer.lineWidth = 5shapeLayer.lineCap = .squareself.view.layer.addSublayer(shapeLayer)}

执行效果如下:

我们可以通过这种方法绘制一个既有圆角又有直角的图形。如果我们想依照此图形来裁剪视图内容,我们可以把CAShapeLayer作为视图的宿主图层,而不是添加一个子视图。

3. CATextLayer

A layer that provides simple text layout and rendering of plain or attributed strings.

一个可以提供简单文本布局以及纯文本或者富文本字符串显示的图层。

class CATextLayer : CALayer

CATextLayer几乎包含了UILabel的所有特性,另外还提供了一些新的特性。并且CATextLayer使用了Core text,渲染要比UILabel快很多。

下面看一些CATextLayer常用的属性:

属性 类型 说明
string Any? 要显示的文本。
font CFTypeRef? 文本字体。可以设置为CTFont或者CGFont,不可以设置为UIFont。
fontSize CGFloat 文本字体大小。
foregroundColor CGColor? 文本字体颜色。
isWrapped Bool 文本是否换行。
alignmentMode CATextLayerAlignmentMode

文本水平对齐方式。

natural:自然对齐方式,默认方式。

left:左对齐。

right:右对齐。

center:居中对齐。

justified:两端对齐。

truncationMode CATextLayerTruncationMode

文本末尾折断方式。

none: 默认方式,如果文本设置了isWrapped为true,那么文本换行显示,直到显示变大折断。

start: 显示不下的话,文档前部分打点显示。

end: 显示不下的话,文档末尾部分打点显示。

middle: 显示不下的话,文档中间部分打点显示。

示例代码如下:

    func textLayerTest() {let textLayer = CATextLayer()textLayer.backgroundColor = UIColor.white.cgColortextLayer.frame = CGRect(x: 50, y: 100, width: 200, height: 200)textLayer.string = "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda."textLayer.contentsScale = UIScreen.main.scaletextLayer.foregroundColor = UIColor.black.cgColortextLayer.alignmentMode = .naturaltextLayer.isWrapped = truetextLayer.truncationMode = .endlet fontName: CFString = "HelveticaNeue-BoldItalic" as CFStringtextLayer.font = CTFontCreateWithName(fontName, 17, nil)textLayer.fontSize = 17self.view.layer.addSublayer(textLayer)}

上面有两个位置需要注意,一个是设置字体,这里采用了CTFontCreateWithName函数设置字体,设置字体大小需要用属性fontSizeCTFontCreateWithName函数里面设置的fontSize不起作用;二是要设置contentsScale属性,对于Retina屏幕,不设置这个属性,显示的文字会有些花掉。设置contentsScale与不设置contentsScale的执行结果分别如下:

   

这里附带一个显示系统所有字体的方法:

    func showAllSystemFonts() {UIFont.familyNames.forEach { (familyName) inprint(familyName + " : ")UIFont.fontNames(forFamilyName: familyName).forEach { (fontName) inprint("\t\(fontName)")}}}

CATextLayer富文本

既然UILabel有富文本功能,那么CATextLayer也有富文本功能。下面看一下CATextLayer的富文本:

    func textLayerAttributeTest() {let textLayer = CATextLayer()textLayer.backgroundColor = UIColor.white.cgColortextLayer.frame = CGRect(x: 50, y: 100, width: 200, height: 200)textLayer.contentsScale = UIScreen.main.scaletextLayer.foregroundColor = UIColor.black.cgColortextLayer.alignmentMode = .naturaltextLayer.isWrapped = truetextLayer.truncationMode = .endlet text = "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda."let attributeString = NSMutableAttributedString(string: text)let attrs1: Dictionary<NSAttributedString.Key, Any> = [NSAttributedString.Key.foregroundColor : UIColor.black.cgColor,NSAttributedString.Key.font : CTFontCreateWithName("HelveticaNeue" as CFString, 15, nil)]attributeString.setAttributes(attrs1, range: NSRange(location: 0, length: text.count))let attrs2: Dictionary<NSAttributedString.Key, Any> = [NSAttributedString.Key.foregroundColor : UIColor.blue.cgColor, NSAttributedString.Key.font : CTFontCreateWithName("HelveticaNeue-BoldItalic" as CFString, 15, nil), NSAttributedString.Key.underlineStyle : NSUnderlineStyle.double.rawValue]attributeString.setAttributes(attrs2, range: NSRange(location: 5, length: 4))textLayer.string = attributeStringself.view.layer.addSublayer(textLayer)}

执行结果图:

4. CATransformLayer

Objects used to create true 3D layer hierarchies, rather than the flattened hierarchy rendering model used by other CALayer classes.

用来创建真正的3D层次结构的模型,而不是其他图层类使用的平面化层次结构渲染模型。

class CATransformLayer : CALayer

说的通俗一些,CATransformLayer就是构建了一个3D的图层空间,而这个空间装着真正需要显示的图层,与普通图层不同,CATransformLayer不会将其子图层至于z=0的平面上。

下面看一个官方给出的Demo,创建一个CATransformLayer图层,然后再创建三个有不同颜色的普通图层,并加入到CATransformLayer图层中,三个颜色图层大小位置都一样,只是zPosition值不同。

    func transformLayerTest() {let layer = CATransformLayer()func layerOfColor(_ color: UIColor, zPosition: CGFloat) -> CALayer {let layer = CALayer()layer.frame = CGRect(x: 70, y: 150, width: 100, height: 100)layer.backgroundColor = color.cgColorlayer.zPosition = zPositionlayer.opacity = 0.5return layer}layer.addSublayer(layerOfColor(.red, zPosition: 20))layer.addSublayer(layerOfColor(.green, zPosition: 30))layer.addSublayer(layerOfColor(.blue, zPosition: 40))var perspective = CATransform3DIdentityperspective.m34 = -1.0 / 100layer.transform = CATransform3DRotate(perspective, 0.1, 0, 1, 0)self.view.layer.addSublayer(layer)}

执行结果如下图:

如果我们不用CATransformLayer图层,而是改为CALayer图层,代码如下:

    func transformLayerTest() {let layer = CALayer()func layerOfColor(_ color: UIColor, zPosition: CGFloat) -> CALayer {let layer = CALayer()layer.frame = CGRect(x: 70, y: 150, width: 100, height: 100)layer.backgroundColor = color.cgColorlayer.zPosition = zPositionlayer.opacity = 0.5return layer}layer.addSublayer(layerOfColor(.red, zPosition: 20))layer.addSublayer(layerOfColor(.green, zPosition: 30))layer.addSublayer(layerOfColor(.blue, zPosition: 40))var perspective = CATransform3DIdentityperspective.m34 = -1.0 / 100layer.transform = CATransform3DRotate(perspective, 0.1, 0, 1, 0)self.view.layer.addSublayer(layer)}

执行结果如下图:

红色和绿色的图层被隐藏掉了,如法看出是一个3D的空间图层。

下面再用CATransformLayer绘制一个立方体,代码如下:

    override func viewDidLoad() {super.viewDidLoad()var transform = CATransform3DIdentitytransform.m34 = -1.0/500self.view.layer.sublayerTransform = transformvar cubeCT = CATransform3DIdentitycubeCT = CATransform3DTranslate(cubeCT, 50, 50, 0)cubeCT = CATransform3DRotate(cubeCT, -CGFloat(Double.pi/4), 1, 0, 0)cubeCT = CATransform3DRotate(cubeCT, -CGFloat(Double.pi/4), 0, 1, 0)let cubeLayer = createCube(transform: cubeCT)self.view.layer.addSublayer(cubeLayer)}// 创建立方体func createCube(transform: CATransform3D) -> CATransformLayer {let cubeLayer = CATransformLayer()cubeLayer.transform = transform// 创建第1个面,即面对我们的面,将该面沿着z轴移动50var ct = CATransform3DIdentityct = CATransform3DTranslate(ct, 0, 0, 50)let face1 = createFaceLayer(transform: ct, color: UIColor.cyan)cubeLayer.addSublayer(face1)// 创建第2个面,即左侧的面,将该面沿着x轴移动-50,然后再沿着y轴旋转-90度ct = CATransform3DMakeTranslation(-50, 0, 0)ct = CATransform3DRotate(ct, -CGFloat(Double.pi/2), 0, 1, 0)let face2 = createFaceLayer(transform: ct, color: UIColor.blue)cubeLayer.addSublayer(face2)// 创建第3个面,即右侧的面,将该面沿着x轴移动50,然后再沿着y轴旋转90度ct = CATransform3DMakeTranslation(50, 0, 0)ct = CATransform3DRotate(ct, CGFloat(Double.pi/2), 0, 1, 0)let face3 = createFaceLayer(transform: ct, color: UIColor.green)cubeLayer.addSublayer(face3)// 创建第4个面,即底部的面,将该面沿着y轴移动50,然后再沿着x轴旋转90度ct = CATransform3DMakeTranslation(0, 50, 0)ct = CATransform3DRotate(ct, CGFloat(Double.pi/2), 1, 0, 0)let face4 = createFaceLayer(transform: ct, color: UIColor.orange)cubeLayer.addSublayer(face4)// 创建第5个面,即顶部的面,将该面沿着y轴移动-50,然后再沿着x轴旋转-90度ct = CATransform3DMakeTranslation(0, -50, 0)ct = CATransform3DRotate(ct, -CGFloat(Double.pi/2), 1, 0, 0)let face5 = createFaceLayer(transform: ct, color: UIColor.brown)cubeLayer.addSublayer(face5)// 创建第6个面,即背对我们的面,将该面沿着z轴移动-50,然后再沿着x轴旋转180度ct = CATransform3DMakeTranslation(0, 0, -50)ct = CATransform3DRotate(ct, CGFloat(Double.pi), 1, 0, 0)let face6 = createFaceLayer(transform: ct, color: UIColor.purple)cubeLayer.addSublayer(face6)return cubeLayer}// 创建立方体的每一个面func createFaceLayer(transform: CATransform3D, color: UIColor) -> CALayer {let layer = CALayer()layer.frame = CGRect(x: 100, y: 100, width: 100, height: 100)layer.backgroundColor = color.cgColorlayer.transform = transformreturn layer}

执行结果图如下:

5. 总结

本文主要讲解了CALayer专用图层中的三个图层(CAShapeLayer、CATextLayer、CATransformLayer)的概念属性以及一些用法。

CAShapeLayer一个通过贝塞尔曲线绘制的图层,渲染速度快,高效使用内存,不会被裁边和像素化。

CATextLayer专门用于显示文本的图层,几乎包含了UILabel的所有特性,并且比UILabel渲染快。

CATransformLayer专门用于构建3D空间的图层。

以上内容如果不正确的地方,还请路过的朋友指正,谢谢!

本篇文章出自https://blog.csdn.net/guoyongming925的博客,如需转载,请标明出处。

iOS CALayer专用图层理解与使用方法一(CAShapeLayer、CATextLayer、CATransformLayer)相关推荐

  1. iOS - CALayer 绘图层

    1.CALayer 绘图层 在 iOS 系统中,你能看得见摸得着的东西基本上都是 UIView,比如一个按钮.一个文本标签.一个文本输入框.一个图标等等,这些都是 UIView.其实 UIView 之 ...

  2. IOS CALayer的属性和使用

    一.CALayer的常用属性 1.@propertyCGPoint position;  图层中心点的位置,类似与UIView的center:用来设置CALayer在父层中的位置:以父层的左上角为原点 ...

  3. iOS软件开发架构理解

    iOS软件开发架构理解 这个东西是硬伤,框架?自带的mvc? 自带的UIViewController UIView UINavigationController 这些算不算?当然算的,cocoa框架嘛 ...

  4. iOS 开发:彻底理解 iOS 内存管理(MRC 篇)

    本文首发于我的个人博客:「程序员充电站」 文章链接:「传送门」 本文更新时间:2021年08月17日17:11:59 本文是 「iOS 开发:彻底理解 iOS 内存管理」系列的「MRC 篇」. 用来对 ...

  5. iOS获取设备的唯一标识的方法总结以及最好的方法

    各种获取设备唯一标识的方法介绍 一.UDID(Unique Device Identifier) UDID的全称是Unique Device Identifier,它就是苹果iOS设备的唯一识别码,它 ...

  6. iOS获取设备的唯一标识的方法

    各种获取设备唯一标识的方法介绍 一.UDID(Unique Device Identifier) UDID的全称是Unique Device Identifier,它就是苹果iOS设备的唯一识别码,它 ...

  7. 机器学习:一步步教你理解反向传播方法

    机器学习:一步步教你理解反向传播方法 时间 2016-09-13 00:35:59  Yong Yuan's blog 原文  http://yongyuan.name/blog/back-propa ...

  8. iOS对UIViewController生命周期和属性方法的解析

    iOS对UIViewController生命周期和属性方法的解析 一.引言 作为MVC设计模式中的C,Controller一直扮演着项目开发中最重要的角色,它是视图和数据的桥梁,通过它的管理,将数据有 ...

  9. behavior php,YII2框架中behavior行为的理解与使用方法示例

    本文实例讲述了YII2框架中behavior行为的理解与使用方法.分享给大家供大家参考,具体如下: YII2中的行为说白了就是对组件功能的扩展,在不改变继承关系的条件下. 行为附加到组件后,行为将注入 ...

最新文章

  1. 洛谷P1550 [USACO08OCT]打井Watering Hole
  2. 自动驾驶规划方法综述
  3. super(Net,self).__init__() 的含义
  4. 出现503错误 怎么办
  5. html怎么给没张图片添加单击事件,如何在Canvas上的图形/图像绑定事件监听的实现...
  6. Configure Javadoc and Source Code for JRE in Eclipse JDT
  7. 19. Window focus() 方法
  8. revit模型怎么在手机上看_怎么在手机上查看建筑模型图??
  9. java-php-python-ssm校园流浪猫图鉴管理系统的设计与实现计算机毕业设计
  10. 25匹马选出最快的3匹马
  11. tcp/ip协议的三次握手4次断开
  12. mac怎么验机,都应该查什么
  13. Uninstalling six-1.4.1:
  14. Ceph 中Pool、PG、OSD的关系
  15. javascript中call的用法总结
  16. 非分区表与分区表相互转换
  17. nohup + 命令实现后台不挂断地运行程序
  18. 《Docker系列》Docker安装Hadoop
  19. 基于jsp的火车票网上订票系统
  20. 【转载】中国特色的免费游戏:下流下贱下作!

热门文章

  1. 以网游服务端的网络接入层设计为例,理解实时通信的技术挑战
  2. 群集系统服务器,多服务器群集 2008
  3. 深度学习与自然语言处理第五次作业——段落分析模型
  4. 在 iOS 6开始 UICollectionView 1
  5. finally的一个妙用
  6. 视觉高精度测量,影响精度的5大关键因素
  7. 温度传感器温度数据LED屏幕展示--物联网服务器搭建
  8. vue移动端横屏手写签名
  9. 项目管理之-项目评估
  10. 胖哥食品网络诊断分析