(作业)animation、transition、UIDynamicAnimator

来源:互联网 发布:国外数据库 编辑:程序博客网 时间:2024/06/06 18:00

第二个作业要求,先来看看吧,很有趣的一些动画效果
这里写图片描述
看要求,a和b都不是很麻烦,之前博主自学的时候接触过,第三个接触不多,老师上课时演示的时候有点着迷了,因为,如果有了这个UIDynamicAnimator,那么愤怒的小鸟就不是很难实现的游戏了(有这么神么?后面再介绍吧)
关于UIDynamicAnimator,CSDN的前辈写得很不错

先来看看第一个用animation实现视图位置、大小、转换的改变吧。其实代码很少,只需要调用UIView的工厂方法即可

func animation() {    let view = UIView(frame: CGRect(x: 300, y: 100, width: 100, height: 100))    view.backgroundColor = UIColor.orange    self.view.addSubview(view)    UIView.animate(withDuration: 3, delay: 0, options: [.repeat, .autoreverse], animations: {        view.frame = CGRect(x: 0, y: 20, width: 10, height: 10)        view.backgroundColor = UIColor.yellow        view.transform = view.transform.rotated(by: CGFloat.pi)    }, completion: nil)}

我们先创建了一个视图,然后调用UIView的animate方法,这个方法有几种,我选择的是这个有5个参数的方法,其中第一个参数设置整个动画完成所需要的时间;第二个参数设置延迟多少秒之后将该动画加入线程队列中(所以真正开始执行动画的时间可能会有一些微妙的延迟);第三个是一些动画的参数选项,参数很多,可以使用数组来搭配,博主这里选择了重复和自动倒转;第四个参数设置动画的内容,我们只需要设置在动画结束那一个时刻的视图的状态,中间的过渡Swift会帮你计算;最后一个参数是动画整体完成之后的一些设置了。
这个动画效果就是一个视图从一个位置移动到另一个位置,并在移动的过程中从橙色变为黄色,并且大小改变的同时旋转。

然后是第二个用transition实现两个视图切换了。这时我们需要先声明两个UIView的属性

var firstView: UIView!var secondView: UIView!

然后初始化这两个UIView并添加一个开始动画的按钮

func transition() {    let btn = UIButton(frame: CGRect(x: 0, y: 300, width: 100, height: 44))    btn.setTitle("切换视图", for: .normal)    btn.setTitleColor(UIColor.black, for: .normal)    btn.addTarget(self, action: #selector(changeView), for: .touchUpInside)    self.view.addSubview(btn)    firstView = UIView(frame: CGRect(x: 100, y: 300, width: 100, height: 100))    firstView.backgroundColor = UIColor.purple    self.view.addSubview(firstView)    secondView = UIView(frame: CGRect(x: 100, y: 300, width: 100, height: 100))    secondView.backgroundColor = UIColor.brown    self.view.addSubview(secondView)}

最后实现动画的执行

@objc func changeView() {    UIView.transition(from: secondView, to: firstView, duration: 3, options: [.transitionCurlUp], completion: nil)}

UIView 的transition方法与animate方法类似,在这里就不过多赘述了。不过这个动画的执行会与最开始的接触有点不同,博主在这里设置了动画是向上卷曲翻页,但这个翻页的动画不是在firstView和secondView的范围内,而是在他们两个的父视图上执行。

最后是UIDynamicAnimator了,这个我称之为力学动画,因为其中可以模拟现实世界的一些力学规律,比如物体受重力的作用、物体间的碰撞、物体受持续的推力或瞬时的推力、物体受吸附力、物体之间或物体与锚点之间的作用力。
我们在使用UIDynamicAnimator时,需要有三个东西
UIDynamicAnimator
UIDynamicBehavior(用其子类)
UIDynamicItem(UIView及其子类都是)
首先我们需要声明或初始化三个属性

var animator: UIDynamicAnimator!var gravity = UIGravityBehavior()var collision = UICollisionBehavior()

UIGravityBehavior为重力的行为,UICollisionBehavior为碰撞的行为
然后我们在方法中就可以随机产生一些视图添加到里面了

func dynamicAnimation() {    animator = UIDynamicAnimator(referenceView: self.view)    animator.addBehavior(gravity)    animator.addBehavior(collision)    collision.translatesReferenceBoundsIntoBoundary = true    Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { (t) in        let x = CGFloat(arc4random() % (UInt32(self.view.frame.width) - 50))        let view = UIView(frame: CGRect(x: x, y: 20, width: 50, height: 50))        view.backgroundColor = UIColor.red        view.layer.borderWidth = 1        view.layer.cornerRadius = 10        self.view.addSubview(view)        self.gravity.addItem(view)        self.collision.addItem(view)    }}

我们在初始化UIDynamicAnimator时传入了一个参考的视图,这个参考视图是用于确定UIDynamicAnimator的参考坐标系的。然后我们设置了UICollisionBehavior的translatesReferenceBoundsIntoBoundary,这个设置为真,就是将参考视图的边界作为碰撞的边界,在这个边界中的Item碰到边界时会有碰撞效果产生。

最后我们来看看最终的效果吧(虽然布局很乱,元素很杂,但是效果是有的)
这里写图片描述

最后贴上所有的代码吧

import UIKitclass ViewController: UIViewController {    var firstView: UIView!    var secondView: UIView!    var animator: UIDynamicAnimator!    var gravity = UIGravityBehavior()    var collision = UICollisionBehavior()    override func viewDidLoad() {        super.viewDidLoad()        // Do any additional setup after loading the view, typically from a nib.        animation()        transition()        dynamicAnimation()    }    func animation() {        let view = UIView(frame: CGRect(x: 300, y: 100, width: 100, height: 100))        view.backgroundColor = UIColor.orange        self.view.addSubview(view)        UIView.animate(withDuration: 3, delay: 0, options: [.repeat, .autoreverse], animations: {            view.frame = CGRect(x: 0, y: 20, width: 10, height: 10)            view.backgroundColor = UIColor.yellow            view.transform = view.transform.rotated(by: CGFloat.pi)        }, completion: nil)    }    func transition() {        let btn = UIButton(frame: CGRect(x: 0, y: 300, width: 100, height: 44))        btn.setTitle("切换视图", for: .normal)        btn.setTitleColor(UIColor.black, for: .normal)        btn.addTarget(self, action: #selector(changeView), for: .touchUpInside)        self.view.addSubview(btn)        firstView = UIView(frame: CGRect(x: 100, y: 300, width: 100, height: 100))        firstView.backgroundColor = UIColor.purple        self.view.addSubview(firstView)        secondView = UIView(frame: CGRect(x: 100, y: 300, width: 100, height: 100))        secondView.backgroundColor = UIColor.brown        self.view.addSubview(secondView)    }    @objc func changeView() {        UIView.transition(from: secondView, to: firstView, duration: 3, options: [.transitionCurlUp], completion: nil)    }    func dynamicAnimation() {        animator = UIDynamicAnimator(referenceView: self.view)        animator.addBehavior(gravity)        animator.addBehavior(collision)        collision.translatesReferenceBoundsIntoBoundary = true        Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { (t) in            let x = CGFloat(arc4random() % (UInt32(self.view.frame.width) - 50))            let view = UIView(frame: CGRect(x: x, y: 20, width: 50, height: 50))            view.backgroundColor = UIColor.red            view.layer.borderWidth = 1            view.layer.cornerRadius = 10            self.view.addSubview(view)            self.gravity.addItem(view)            self.collision.addItem(view)        }    }    override func didReceiveMemoryWarning() {        super.didReceiveMemoryWarning()        // Dispose of any resources that can be recreated.    }}