(作业)animation、transition、UIDynamicAnimator

第二个作业要求,先来看看吧,很有趣的一些动画效果
这里写图片描述
看要求,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 UIKit

class 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.
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值