iOS核心动画

一、核心动画种类

1.基础动画
2.转场动画
3.弹簧动画
4.关键帧动画
5.动画组(对上面的动画合并的一种说法)

二、上代码

  1. 基础动画
class BasicAnimaViewController: UIViewController {
    var redView: UIView!
    // 动画key
    let position = "position" // 位移
     
    /**
     * 旋转
     */
    let zRotation = "transform.rotation"
    let xRotation = "transform.rotation.x"
    let yRotation = "transform.rotation.y"
    
    /**
     * 缩放
     */
    let zScale = "transform.scale"
    let xScale = "transform.scale.x"
    let yScale = "transform.scale.y"
    
    /**
     * transform 动画
     */
    let transformAnim = "transform"
    
    
    // 自定义动画的key
    let kMoveredViewAnima = "kMoveredViewAnima"
    let kZRotation = "kZRotation"
    let kXRotation = "kXRotation"
    let kYRotation = "kYRotation"
    
    let kZScale = "kZScale"
    let kXScale = "kXScale"
    let kYScale = "kYScale"
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "基础动画"
        
        redView = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 70))
        redView.backgroundColor = .red
        view.addSubview(redView)
        
//        simpleMove()
//        RotationZ()
//        RotationX()
//        RotationY()
//        scaleY()
        transformAnimation()
    }

    func simpleMove() {
        // 简单位移
        let animation = CABasicAnimation(keyPath: position)
        animation.fromValue = redView.center
        animation.toValue = CGPoint(x:redView.center.x,y:redView.center.y + 100)
        animation.repeatCount = 2
        animation.duration = 3
        animation.beginTime = CACurrentMediaTime() + 1
        
        redView.layer.add(animation, forKey: kMoveredViewAnima)
        
        
    }

    func RotationZ() {
        let animation = CABasicAnimation(keyPath: zRotation)
        animation.repeatCount = 2
        animation.duration = 3
        animation.fromValue = 0
        animation.toValue = .pi * 2.0
        animation.beginTime = CACurrentMediaTime() + 1
        
        redView.layer.add(animation, forKey: kZRotation)
    }
    
    func RotationX() {
        let animation = CABasicAnimation(keyPath: xRotation)
        animation.repeatCount = 2
        animation.duration = 3
        animation.fromValue = 0
        animation.toValue = .pi * 2.0
        animation.beginTime = CACurrentMediaTime() + 1
        
        redView.layer.add(animation, forKey: kXRotation)
    }
    
    func RotationY() {
        let animation = CABasicAnimation(keyPath: yRotation)
        animation.repeatCount = 2
        animation.duration = 3
        animation.fromValue = 0
        animation.toValue = .pi * 2.0
        animation.beginTime = CACurrentMediaTime() + 1
        
        redView.layer.add(animation, forKey: kYRotation)
    }
    
    func scaleZ() {
        let animation = CABasicAnimation(keyPath: zScale)
        animation.repeatCount = 2
        animation.duration = 3
        animation.fromValue = 1
        animation.toValue = 1.5
        animation.beginTime = CACurrentMediaTime() + 1
        
        redView.layer.add(animation, forKey: kZScale)
    }
    
    func scaleX() {
        let animation = CABasicAnimation(keyPath: xScale)
        animation.repeatCount = 2
        animation.duration = 3
        animation.fromValue = 1
        animation.toValue = 1.5
        animation.beginTime = CACurrentMediaTime() + 1
        
        redView.layer.add(animation, forKey: kXScale)
    }
    
    func scaleY() {
        let animation = CABasicAnimation(keyPath: yScale)
        animation.repeatCount = 2
        animation.duration = 3
        animation.fromValue = 1
        animation.toValue = 1.5
        animation.beginTime = CACurrentMediaTime() + 1
        
        redView.layer.add(animation, forKey: kYScale)
    }
    
    func transformAnimation() { // ?
        let animation = CABasicAnimation(keyPath: transformAnim)
        animation.repeatCount = 5
        animation.duration = 3
//        animation.fromValue = 1
//        animation.toValue = 1.5
        animation.beginTime = CACurrentMediaTime() + 1
        
        var transform = CATransform3DMakeRotation(CGFloat(Double.pi), 1, 1, 1)
//        transform.m34 = -1.0/600.0
        
        animation.byValue = transform
        
        redView.layer.add(animation, forKey: kYScale)
    }

}
  1. 转场动画
class translationAnimaViewController: UIViewController {

    let imageView = UIImageView()
    // type
    let typeRippleEffect = "rippleEffect"
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "转场动画"
        
        setUI()
    }
    
    func setUI() {
        imageView.frame = CGRect(x: 100, y: 100, width: 200, height: 200)
//        imageView.center = view.center
        imageView.image = UIImage(named: "abc")
        view.addSubview(imageView)
        
        let btn = UIButton(type: .custom)
        btn.frame = CGRect(x: 0, y: view.bounds.height - 150, width: 50, height: 30)
        btn.center = CGPoint(x: view.bounds.width/2.0 - 100, y: view.bounds.height - 130)
        btn.backgroundColor = .green
        btn.setTitle("切换", for: .normal)
        btn.addTarget(self, action: #selector(change(_:)), for: .touchUpInside)
        view.addSubview(btn)
        
    }
    /**
     fade:默认,交叉淡化过渡,不支持过渡方向,OC中对应的常量为kCATransitionFade
     push:新视图把旧视图推出去,OC中对应的常量为kCATransitionPush
     moveIn:新视图移到旧视图上面,对应的常量为kCATransitionMoveIn
     reveal:将旧视图移开显示下边的新视图,对应的常量为kCATransitionReveal
     cube:立方体反转效果
     oglFlip:上下左右反转效果
     suckEffect:收缩效果,如一块布被抽走,不支持过渡方向
     rippleEffect:滴水效果,不支持过渡方向
     pageCurl:向上翻页效果
     pageUnCurl:向下翻页效果
     cameraIrisHollowOpen:相机镜头打开效果,不支持过渡方向
     cameraIrisHollowClose:相机镜头关闭效果,不支持过渡方向
     */
    
    @objc func change(_ sender: UIButton) {
        let animation = CATransition()
        animation.type = CATransitionType(rawValue: "push")
        animation.duration = 3
        animation.subtype = .fromTop
        animation.fillMode = .forwards
        imageView.layer.add(animation, forKey: "change")
        imageView.image = UIImage(named: "001")
    }


}
  1. 弹簧动画
class SpringAnimaViewController: UIViewController {
    var redView: UIView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "弹簧动画"
        
        redView = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 70))
        redView.backgroundColor = .red
        view.addSubview(redView)
        
        CASpringAnim()
        
    }

    func springAnim() {
        UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.6, options: [.autoreverse,.repeat]) {
            self.redView.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
        } completion: { _ in
            
        }
    }
    
    func CASpringAnim() {
        let animtion = CASpringAnimation(keyPath: "transform.scale")
        animtion.beginTime = CACurrentMediaTime()
        animtion.mass = 0.1 // 质量越大,惯性越大
        animtion.damping = 1 // 阻尼系数
        animtion.stiffness = 100 // 刚性系数,刚性系数越大,运动越快
        animtion.initialVelocity = 0.3 // 初始速率
        animtion.toValue = 1.5
        animtion.repeatCount = HUGE
        animtion.autoreverses = false
        animtion.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
        animtion.duration = animtion.settlingDuration // 系统根据动画参数估算的时间
        
        redView.layer.add(animtion, forKey: "CASpringAnim")
    }

}
  1. 关键帧动画
class keyFrameViewController: UIViewController {
    var redView: UIView!
    // 动画key
    let position = "position" // 位移
    let zRotation = "transform.rotation"
    
    
    // 自定义动画的key
    let kMoveredViewAnima = "kMoveredViewAnima"
    let kShakeAnim = "kShakeAnim"
    let kTranslate = "kTranslate"
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "关键帧动画"
        
        redView = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 70))
        redView.backgroundColor = .red
        view.addSubview(redView)
        
        renderM()
        
    }
    
    func simpleMove() {
        // 简单位移
        let animation = CAKeyframeAnimation(keyPath: position)
        animation.repeatCount = 2
        animation.duration = 3
        // 移动轨迹
        animation.values = [redView.center,CGPoint(x: 200, y: 200),CGPoint(x: 200, y: 300)]
        // 每段路程经过的时间,时间节点比例
        animation.keyTimes = [NSNumber(value: 0.0),NSNumber(value: 0.7),NSNumber(value: 1.0),]
        animation.beginTime = CACurrentMediaTime() + 1
        animation.isRemovedOnCompletion = false
        animation.autoreverses = true
        
        // 拐弯的地方轨迹变平滑
        animation.calculationMode = .cubic
        
        redView.layer.add(animation, forKey: kMoveredViewAnima)
    }
    
    func simpleMoveByPath() {
        // 简单位移
        let animation = CAKeyframeAnimation(keyPath: position)
        animation.repeatCount = 2
        animation.duration = 3
        // 移动轨迹
        animation.values = [redView.center,CGPoint(x: 200, y: 200),CGPoint(x: 200, y: 300)] // 失效
        // 每段路程经过的时间,时间节点比例
//        animation.keyTimes = [NSNumber(value: 0.0),NSNumber(value: 0.7),NSNumber(value: 1.0),]
        animation.beginTime = CACurrentMediaTime() + 1
        animation.isRemovedOnCompletion = false
        animation.autoreverses = true
        
        // 拐弯的地方轨迹变平滑
//        animation.calculationMode = .cubic
        
        // 添加path,values失效
        let path = CGMutablePath()
        path.addArc(center: view.center, radius: 100, startAngle: 0, endAngle: CGFloat(Double.pi * 2), clockwise: true)
        animation.path = path
        
        
        redView.layer.add(animation, forKey: kMoveredViewAnima)
    }
    
    func shakeAnim() {
        let label = UILabel(frame: redView.bounds)
        label.textAlignment = .center
        label.textColor = .white
        label.text = "摇一摇"
        redView.addSubview(label)
        
        let animation = CAKeyframeAnimation(keyPath: zRotation)
        animation.duration = 0.3
        let angle = Double.pi/6.0
        animation.values = [angle, -angle]
        animation.repeatCount = 3
        animation.autoreverses = true
        animation.calculationMode = .cubicPaced
        
        redView.layer.add(animation, forKey: kShakeAnim)
    }
    
    func renderM() {
        let label = UILabel(frame: redView.bounds)
        label.textAlignment = .center
        label.textColor = .white
        label.text = "画M"
        redView.addSubview(label)
        
        let animation = CAKeyframeAnimation(keyPath: position)
        animation.duration = 5
        
        let path = CGMutablePath()
        path.move(to: CGPoint(x: 40, y: 300))
        path.addLine(to: CGPoint(x: 80, y: 150))
        path.addLine(to: CGPoint(x: 120, y: 300))
        path.addLine(to: CGPoint(x: 160, y: 150))
        path.addLine(to: CGPoint(x: 200, y: 300))
        animation.path = path
        
        animation.repeatCount = HUGE
//        animation.rotationMode = .rotateAuto // 跟随运动方向自旋转
        animation.calculationMode = .cubicPaced
        animation.fillMode = .forwards
        
        redView.layer.add(animation, forKey: kTranslate)
    }

}
  1. 动画组
class AnimaGroupViewController: UIViewController {
    let imageView = UIImageView()
    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "动画组"
        
        setUI()
    }

    func setUI() {
        imageView.frame = CGRect(x: 100, y: 100, width: 200, height: 100)
        imageView.image = UIImage(named: "001")
        view.addSubview(imageView)
        
        let btn = UIButton(type: .custom)
        btn.frame = CGRect(x: 160, y: 250, width: 80, height: 40)
        btn.setTitle("切换", for: .normal)
        btn.backgroundColor = .blue
        btn.addTarget(self, action: #selector(change(_:)), for: .touchUpInside)
        view.addSubview(btn)
    }
    
    @objc func change(_ sender: UIButton) {
        sender.isSelected = !sender.isSelected
        if sender.isSelected {
            let transition = CABasicAnimation(keyPath: "position")
            transition.toValue = CGPoint(x: 100, y: 400)
//            transition.autoreverses = true
            
            let rotation = CABasicAnimation(keyPath: "transform.rotation.z")
            rotation.fromValue = 0
            rotation.toValue = Double.pi * 2
            
            let scale = CABasicAnimation(keyPath: "transform.scale")
            scale.toValue = 0.5
            
            let group = CAAnimationGroup()
            group.animations = [transition, rotation, scale]
            group.repeatCount = HUGE
            group.duration = 2
            group.autoreverses = true
            
            imageView.layer.add(group, forKey: "group")
        } else {
            imageView.layer.removeAllAnimations()
        }
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值