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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:CALayer相关文章
下一篇:iOS自定义控件二

发表评论

最新留言

很好
[***.229.124.182]2024年04月04日 05时02分45秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章