美文网首页
iOS动画效果实战篇之CABasicAnimation的使用

iOS动画效果实战篇之CABasicAnimation的使用

作者: 超zd | 来源:发表于2018-09-30 12:00 被阅读95次

    最近正在研究iOS动画效果的实现,目的也是为了自己能够写出比较炫酷的动画效果。趁着项目不怎么忙,抽出时间写篇文章来记录一下自己的学习成果及实战效果。由于本人是最近才开始写博客,不善言辞,不喜勿喷,如果错误,还请指正。
    本篇文章的动画效果也是我在学习动画效果的过程中其中一个页面的动画效果。

    效果展示

    CABaseAnimation.gif

    非常简单的一个按钮动画效果,有兴趣的同学可以自己动手实现一下。我再这里界面布局是用的Stroyboard,手写代码的话也非常简单。

    布局

    布局我就不多说了,拖几个控件再把约束加上就行了,这里主要说一下登录按钮的约束。
    1.左右两边约束。2.居中约束。3.高度约束。4.宽高比约束。
    这里注意一点,在Storyboard中将登录按钮右侧的约束的Installed属性对勾去掉,否则会有警告信息,不过并不影响效果

    下面我就直接上代码了。我的编译环境是Xcode10 + Swift4.2,OC版本自己转化一下就可以了

    下面是ViewController中代码

    import UIKit
    
    class ViewController: UIViewController {
    
        @IBOutlet weak var loginButton: UIButton!
        @IBOutlet weak var ratioConstraint: NSLayoutConstraint!//宽高比约束
        @IBOutlet weak var rightConstraint: NSLayoutConstraint!//右侧约束
        @IBOutlet weak var leftConstraint: NSLayoutConstraint!//左侧约束
    
        //旋转动画效果的图层,动画的旋转效果都在这个图层中实现
        private var testLayer: ActivityLayer!
        
        private var isAnimation: Bool = false
        
        override func viewDidLoad() {
            super.viewDidLoad()
            self.loginButton.layer.cornerRadius = 22.5
        }
        
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
        }
    
        @IBAction func clickLogin(_ sender: UIButton) {
            
            //模拟网络请求
            self.shrinkLoginButton()
            DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                self.spreadLoginButton()
            }
        }
        //按钮缩小动画
        private func shrinkLoginButton() {
            
            self.leftConstraint.isActive = false
            self.rightConstraint.isActive = false
            
            let ratioC = NSLayoutConstraint(item: self.loginButton, attribute:NSLayoutConstraint.Attribute.width , relatedBy:.equal , toItem: self.loginButton, attribute: NSLayoutConstraint.Attribute.height, multiplier: 1.0, constant: 0)
            ratioC.isActive = true
            self.ratioConstraint = ratioC
            
            UIView.animate(withDuration: 0.25, animations: {
                self.view.layoutIfNeeded()
                self.loginButton.setTitleColor(UIColor(white: 1, alpha: 0), for: .normal)
            }) { (finished) in
                if finished {
                    self.testLayer = ActivityLayer.init(self.loginButton.bounds)
                    self.loginButton.layer.addSublayer(self.testLayer)
                    self.testLayer.startAnimation()
                }
            }
        }
        //按钮拉长动画
        private func spreadLoginButton() {
            
            self.ratioConstraint.isActive = false
            
            let leftC = NSLayoutConstraint(item: self.loginButton, attribute: NSLayoutConstraint.Attribute.left, relatedBy: .equal, toItem: self.loginButton.superview, attribute: NSLayoutConstraint.Attribute.left, multiplier: 1.0, constant: 25.0)
            let rightC = NSLayoutConstraint(item: self.loginButton, attribute: NSLayoutConstraint.Attribute.right, relatedBy: .equal, toItem: self.loginButton.superview, attribute: NSLayoutConstraint.Attribute.right, multiplier: 1.0, constant: -25.0)
            
            leftC.isActive = true
            rightC.isActive = true
            self.leftConstraint = leftC
            self.rightConstraint = rightC
            
            self.testLayer.removeFromSuperlayer()
            UIView.animate(withDuration: 0.25) {
                self.view.layoutIfNeeded()
                self.loginButton.setTitleColor(UIColor(white: 1, alpha: 1), for: .normal)
            }
        }
        
    }
    

    以下是ActivityLayer的实现

    import UIKit
    class ActivityLayer: CALayer {
        
        let spaceWidth: CGFloat = 3.0
        let lineWidth: CGFloat = 3.0
    
        private lazy var shaperLayer: CAShapeLayer = {
            
            let path = UIBezierPath(arcCenter: CGPoint.zero, radius: self.frame.height / 2.0 - spaceWidth - lineWidth, startAngle: CGFloat(-Double.pi / 2), endAngle: 0, clockwise: true)
            let shaperLayer = CAShapeLayer()
            shaperLayer.position = self.position//如果不加这句那shaperLayer会绕着(0,0)点旋转。
            shaperLayer.fillColor = UIColor.clear.cgColor
            shaperLayer.strokeColor = UIColor.white.cgColor
            shaperLayer.lineWidth = lineWidth
            shaperLayer.path = path.cgPath
            return shaperLayer
        }()
        
        override init() {
            super.init()
        }
        
        convenience init(_ frame: CGRect) {
            self.init()
            self.frame = frame
            self.addSublayer(self.shaperLayer)
            
            let baseAnimation = CABasicAnimation()
            baseAnimation.duration = 0.25
            baseAnimation.keyPath = "transform"
            baseAnimation.isRemovedOnCompletion = false
            baseAnimation.fillMode = .forwards
            baseAnimation.isCumulative = true
            baseAnimation.repeatCount = MAXFLOAT
            //CATransform3DMakeRotation 当顺时针和逆时针路径相同时,总是使用逆时针,此时设置z轴的正负没有效果
            //CATransform3DMakeRotation(CGFloat(Double.pi), 0, 0, 1)以及CATransform3DMakeRotation(CGFloat(Double.pi), 0, 0, -1)都是逆时针
            let transform = CATransform3DMakeRotation(CGFloat(Double.pi) / 2, 0, 0, 1)
            baseAnimation.toValue = NSValue(caTransform3D: transform)
            self.shaperLayer.add(baseAnimation, forKey: nil)
        }
        
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        func startAnimation() {
            
            let pauseTime = self.shaperLayer.timeOffset
            self.shaperLayer.speed = 1
            self.shaperLayer.timeOffset = 0
            self.shaperLayer.beginTime = 0
            
            let timeSincePause = self.shaperLayer.convertTime(CACurrentMediaTime(), from: nil) - pauseTime
            self.shaperLayer.beginTime = timeSincePause
        }
        
        func stopAnimation() {
            
            let pausedTime = self.shaperLayer.convertTime(CACurrentMediaTime(), from: nil)
            self.shaperLayer.speed = 0.0
            self.shaperLayer.timeOffset = pausedTime
        }
    }
    

    相关文章

      网友评论

          本文标题:iOS动画效果实战篇之CABasicAnimation的使用

          本文链接:https://www.haomeiwen.com/subject/wbtwoftx.html