CALayer基础
发布日期:2022-03-18 08:27:40
浏览次数:37
分类:技术文章
本文共 5256 字,大约阅读时间需要 17 分钟。
参考
CALayer基础
补充
参考
每个图层属性的显示值都被存储在一个叫做呈现图层的独立图层当中,他可以通过
-presentationLayer
方法来访问。这个呈现图层实际上是模型图层的复制,但是它的属性值代表了在任何指定时刻当前外观效果。换句话说,你可以通过呈现图层的值来获取当前屏幕上真正显示出来的值
CAShapeLayer
该例子使用了CAShapeLayer
制作了一个指示器,改变时有动画
该例子的效果如下:
主要实现方式是:
1.一个背景layer,一个前置的layer 2.CABasicAnimation动画,改变strokeEnd代码如下StatView
:
import UIKit@IBDesignableclass StatView: UIView { let percentLabel = UILabel() let captionLabel = UILabel() var range: CGFloat = 10 var curValue: CGFloat = 0 { didSet { animate() } } let margin: CGFloat = 10 //背景layer let bgLayer = CAShapeLayer() @IBInspectable var bgColor: UIColor = UIColor.grayColor() { didSet { configure() } } //前面的layer let fgLayer = CAShapeLayer() @IBInspectable var fgColor: UIColor = UIColor.blackColor() { didSet { configure() } } override func awakeFromNib() { super.awakeFromNib() setup() configure() } //Called when a designable object is created in Interface Builder. override func prepareForInterfaceBuilder() { super.prepareForInterfaceBuilder() setup() configure() } func setup() { // Setup background layer bgLayer.lineWidth = 20.0 bgLayer.fillColor = nil bgLayer.strokeEnd = 1 layer.addSublayer(bgLayer) //设置fgLayer fgLayer.lineWidth = 20.0 fgLayer.fillColor = nil fgLayer.strokeEnd = 0 layer.addSublayer(fgLayer) // Setup percent label percentLabel.font = UIFont.systemFontOfSize(26) percentLabel.textColor = UIColor.whiteColor() percentLabel.text = "0/0" percentLabel.translatesAutoresizingMaskIntoConstraints = false addSubview(percentLabel) // Setup caption label captionLabel.font = UIFont.systemFontOfSize(26) captionLabel.text = "Chapters Read" captionLabel.textColor = UIColor.whiteColor() captionLabel.translatesAutoresizingMaskIntoConstraints = false addSubview(captionLabel) // Setup constraints let percentLabelCenterX = percentLabel.centerXAnchor.constraintEqualToAnchor(self.centerXAnchor) let percentLabelCenterY = percentLabel.centerYAnchor.constraintEqualToAnchor(self.centerYAnchor, constant: -margin) NSLayoutConstraint.activateConstraints([percentLabelCenterX, percentLabelCenterY]) let captionLabelCenterX = captionLabel.centerXAnchor.constraintEqualToAnchor(self.centerXAnchor, constant: -margin) let captionLabelBottom = captionLabel.bottomAnchor.constraintEqualToAnchor(self.bottomAnchor, constant: -margin) NSLayoutConstraint.activateConstraints([captionLabelCenterX, captionLabelBottom]) } func configure() { bgLayer.strokeColor = bgColor.CGColor fgLayer.strokeColor = fgColor.CGColor } //重写layoutSubviews override func layoutSubviews() { super.layoutSubviews() setupShapeLayer(bgLayer) setupShapeLayer(fgLayer) } //设置path private func setupShapeLayer(shapeLayer:CAShapeLayer) { shapeLayer.frame = self.bounds let startAngle = DegreesToRadians(135.0) let endAngle = DegreesToRadians(45.0) let center = percentLabel.center let radius = CGRectGetWidth(self.bounds) * 0.35 let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true) shapeLayer.path = path.CGPath } private func animate() { percentLabel.text = String(format: "%.0f/%.0f", curValue, range) var fromValue = fgLayer.strokeEnd let toValue = curValue / range if let presentationLayer = fgLayer.presentationLayer() as? CAShapeLayer { fromValue = presentationLayer.strokeEnd } let percentChange = abs(fromValue - toValue) // 创建CABasicAnimation动画 let animation = CABasicAnimation(keyPath: "strokeEnd") animation.fromValue = fromValue animation.toValue = toValue // 动画时间 animation.duration = CFTimeInterval(percentChange * 4) // 移除stroke动画,再添加 fgLayer.removeAnimationForKey("stroke") fgLayer.addAnimation(animation, forKey: "stroke") CATransaction.begin() CATransaction.setDisableActions(true) fgLayer.strokeEnd = toValue CATransaction.commit() }}
说明:
在一个layer上运行动画时,animation其实是在一个叫做presentation layer上发生的,可以把它认为是layer的复制,仅用于animation。
动画改变的属性是位于presentation layer上的,当动画完成后,presentation layer就会被消失,然后就只看见了原来的layer。所以animation并不会自动更新original layer上的属性,需要添加上:fgLayer.strokeEnd = toValue
还要注意的是改变layer的属性(例如strokeEnd
)会自动触发一个隐式动画(implicit animation)。由于已经运行了自己动画,所以要disable这个隐式动画,以免冲突:
CATransaction.begin()CATransaction.setDisableActions(true)fgLayer.strokeEnd = toValueCATransaction.commit()
还要注意的是,fromValue
要取presentationLayer的值:
if let presentationLayer = fgLayer.presentationLayer() as? CAShapeLayer{ fromValue = presentationLayer.strokeEnd}
Layer Mask
Layers have a mask
property
- Fully or partially opaque pixels: shows content
- Transparent pixels: hides content
可以对view设置mask,显示圆形图像:
let maskLayer = CAShapeLayer()maskLayer.path = UIBezierPath(ovalInRect: layerAvatar.bounds).CGPathlayerAvatar.mask = maskLayerlayerAvatar.path = maskLayer.path
转载地址:https://windzen.blog.csdn.net/article/details/53421695 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
很好
[***.229.124.182]2024年04月04日 05时02分45秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
【开发篇】10分钟快速spring boot+react前后端分离
2019-04-26
【Leetcode刷题篇】leetcode203 移除链表元素
2019-04-26
【Leetcode刷题篇】leetcode938 二叉搜索树的范围和
2019-04-26
【Leetcode刷题篇】leetcode703 数据流中的第k大元素
2019-04-26
【Java网络编程与IO流】Java中BIO、NIO、AIO的区别是什么?
2019-04-26
【Leetcode刷题篇】leetcode136 只出现一次的数字
2019-04-26
spring boot整合thymeleaf,支持JSP和HTML页面开发
2019-04-26
【Java网络编程与IO流】Spring boot整合SSE实现服务器实时推送流信息
2019-04-26
【Leetcode刷题篇】leetcode141 环形链表II
2019-04-26
【Leetcode刷题篇】leetcode160 相交链表
2019-04-26
【Leetcode刷题篇】leetcode169 多数元素
2019-04-26
【Leetcode刷题篇】leetcode461 汉明距离
2019-04-26
【Leetcode刷题篇】leetcode204 计数质数
2019-04-26
【Leetcode刷题篇】leetcode70 爬楼梯
2019-04-26
【Leetcode刷题篇】leetcode739 每日温度
2019-04-26
【Leetcode刷题篇】leetcode121买卖股票的最佳时机
2019-04-26
【面试篇】Java多线程并发-Java关键字volatile详解
2019-04-26
【面试篇】Java的代理模式-静态代理和动态代理详解
2019-04-26
【面试篇】 Java对象拷贝(对象克隆 对象复制)
2019-04-26