当前位置: > > > Swift - 动画效果的实现方法总结(附样例)

Swift - 动画效果的实现方法总结(附样例)

(本文代码已升级至Swift3)

iOS 中,实现动画有两种方法。一个是统一的 animate,另一个是组合出现的 beginAnimations commitAnimations。这三个方法都是类方法。

一,使用 animate 来实现动画


(1)此方法共有5个参数:
  • withDuration:动画从开始到结束的持续时间,单位是秒
  • delay:动画开始前等待的时间
  • options:动画执行的选项。里面可以设置动画的效果。可以使用 UIViewAnimationOptions 类提供的各种预置效果
  • anmations:动画效果的代码块
  • completion:动画执行完毕后执行的代码块
(2)UIView支持动画效果的属性
  • frame:此属性包含一个矩形,即边框矩形,此值确定了当前视图在其父视图坐标系中的位置与尺寸
  • bounds:也是矩形,边界矩形,它指的是视图在其自己的坐标系中的位置和尺寸,左上角坐标永远是 (0,0)
  • center:确定视图的中心点在其父视图坐标系中的位置坐标。即定义当前视图在父视图中的位置
  • alpha:视图的透明度。(但视图完全透明时,不能响应触摸消息)
  • backgroundColor:背景色
  • transform:这是一种 3×3 的变化矩阵。通过这个矩阵我们可以对一个坐标系统进行缩放、平移、旋转以及这两者的任意组操作。
(3)Transform(变化矩阵)的四个常用的变换方法
  • CGAffineTransformMake():返回变换矩阵
  • CGAffineTransformMakeTranslation():返回平移变换矩阵
  • CGAffineTransformMakeScale():返回缩放变换矩阵
  • CGAffineTransformMakeRotation():返回旋转变换矩阵
(4)样例1:方块初始缩小为原始尺寸1/10。在1秒的动画中复原到完整大小,同时还伴随旋转效果。
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import UIKit
 
class ViewController: UIViewController {
     
    //游戏方格维度
    var dimension:Int = 4
    //数字格子的宽度
    var width:CGFloat = 50
    //格子与格子的间距
    var padding:CGFloat = 6
     
    //保存背景图数据
    var backgrounds:Array<UIView>!
     
    override func viewDidLoad()
    {
        super.viewDidLoad()
        self.backgrounds = Array<UIView>()
        setupGameMap()
        playAnimation()
    }
     
    func setupGameMap()
    {
        var x:CGFloat = 50
        var y:CGFloat = 150
         
        for i in 0..<dimension
        {
            print(i)
            y = 150
            for _ in 0..<dimension
            {
                //初始化视图
                let background = UIView(frame:CGRect(x:x, y:y,
                                                     width:width, height:width))
                background.backgroundColor = UIColor.darkGray
                self.view.addSubview(background)
                //将视图保存起来,以备后用
                backgrounds.append(background)
                y += padding + width
            }
            x += padding+width
        }
    }
     
    func playAnimation()
    {
        for tile in backgrounds{
            //先将数字块大小置为原始尺寸的 1/10
            tile.layer.setAffineTransform(CGAffineTransform(scaleX: 0.1,y: 0.1))
             
            //设置动画效果,动画时间长度 1 秒。
            UIView.animate(withDuration: 1, delay:0.01, options: [], animations: {
                ()-> Void in
                //在动画中,数字块有一个角度的旋转。
                tile.layer.setAffineTransform(CGAffineTransform(rotationAngle: 90))
            },
            completion:{
                (finished:Bool) -> Void in
                UIView.animate(withDuration: 1, animations:{
                    ()-> Void in
                    //完成动画时,数字块复原
                    tile.layer.setAffineTransform(CGAffineTransform.identity)
                })
            })
        }
    }
     
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

(5)样例2:只有从小变大的效果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
func playAnimation()
{
    for tile in backgrounds{
        //先将数字块大小置为原始尺寸的 1/10
        tile.layer.setAffineTransform(CGAffineTransform(scaleX: 0.1,y: 0.1))
         
        //设置动画效果,动画时间长度 1 秒。
        UIView.animate(withDuration: 1, delay:0.01, options:[], animations: {
            ()-> Void in
            tile.layer.setAffineTransform(CGAffineTransform(scaleX: 1,y: 1))
        },
        completion:{
            (finished:Bool) -> Void in
            UIView.animate(withDuration: 0.08, animations:{
                ()-> Void in
                tile.layer.setAffineTransform(CGAffineTransform.identity)
            })
        })
    }
}
(6)样例3:方块从不透明到透明的效果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func playAnimation()
{
    for tile in backgrounds{
        tile.alpha = 0
         
        //设置动画效果,动画时间长度 1 秒。
        UIView.animate(withDuration: 1, delay:0.01, options:[.curveEaseInOut],
                       animations: {
                        ()-> Void in
        },
        completion:{
            (finished:Bool) -> Void in
            UIView.animate(withDuration: 1, animations:{
                ()-> Void in
                tile.alpha = 1
            })
        })
    }
}

二,使用 beginAnimations 和 commitAnimations 方法来实现动画

  • beginAnimations:此方法开始一个动画块,调用 commitAnimations 结束一个动画块,并且动画块是允许嵌套的。
  • commitAnimations:此方法用于结束一个动画块,动画是在一个独立的线程中运行的,动画在生效时,所有应用程序不会中断。
beginAnimations commitAnimations 中间的代码中,我们可以设置各种动画的属性。比如持续时间,使用哪种预置的动画效果等。

(1)淡入,淡出,移动,改变大小动画
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//淡出动画
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(2.0)
imageView.alpha = 0.0
UIView.commitAnimations()
 
//淡入动画
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(2.0)
imageView.alpha = 1.0
UIView.commitAnimations()
 
//移动动画
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(2.0)
imageView.center = CGPoint(x:250, y:250)
UIView.setAnimationCurve(.easeOut) //设置动画相对速度
UIView.commitAnimations()
 
//大小调整动画
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(2.0)
imageView.frame = CGRect(x:100, y:180, width:50, height:50)
UIView.commitAnimations()

(2)两个视图切换的过渡动画
  UIViewAnimationTransition定义了 5 种过渡动画类型:
  • none:无过渡动画效果
  • flipFromLeft:从左侧向右侧翻转
  • flipFromRight:从右侧向左侧翻转
  • curlUp:向上卷数翻页
  • curlDown:向下翻页
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import UIKit
 
class ViewController: UIViewController {
     
    override func viewDidLoad()
    {
        super.viewDidLoad()
         
        //创建一个按钮,用来点击播放动画
        let button:UIButton = UIButton(type:.system)
        button.frame=CGRect(x:10, y:20, width:100, height:30)
        button.setTitle("播放动画", for:.normal)
        button.addTarget(self,action:#selector(ViewController.play),
                         for:.touchUpInside)
        self.view.addSubview(button)
         
        //添加两个红蓝视图
        let redView = UIView(frame: CGRect(x:50, y:50, width:150, height:400))
        redView.backgroundColor = UIColor.red
        self.view.insertSubview(redView, at: 0)
         
        let blueView = UIView(frame: CGRect(x:50, y:50, width:150, height:400))
        blueView.backgroundColor = UIColor.blue
        self.view.insertSubview(blueView, at: 1)
    }
     
    //切换视图并播放动画
    func play(){
        UIView.beginAnimations(nil, context: nil)
        UIView.setAnimationDuration(3.0)
        UIView.setAnimationTransition(.curlUp, for: self.view, cache: true)
        self.view.exchangeSubview(at: 1, withSubviewAt: 0)
        UIView.commitAnimations()
    }
     
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

(3)页面或元件翻转效果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import UIKit
 
class ViewController: UIViewController {
     
    override func viewDidLoad()
    {
        super.viewDidLoad()
         
        //创建一个按钮,用来点击播放动画
        let button = UIButton(type:.system)
        button.frame = CGRect(x:10, y:20, width:100, height:30)
        button.setTitle("播放动画", for:.normal)
        button.addTarget(self,action:#selector(ViewController.play),
                         for:.touchUpInside)
        self.view.addSubview(button);
    }
     
    //切换视图并播放动画
    func play(){
        //将整个主视图面板实现一个翻转效果
        UIView.beginAnimations("animation", context: nil)
        UIView.setAnimationDuration(2)
        UIView.setAnimationCurve(.easeInOut)
        UIView.setAnimationTransition(.flipFromLeft, for: self.view, cache: false)
        UIView.commitAnimations()
    }
     
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}
评论2
  • 2楼
    2017-09-18 10:33
    mimosa

    想问一下 我有两个viewcontroller 第二个里面写有动画效果 我从第一个present到第二个之后第二个vc里面的动画就不执行了直接显示结果?

    站长回复

    我这边测试了下第二个VC中的动画也是执行的,不太清楚你那边是什么问题了。

  • 1楼
    2016-04-30 00:54
    sean

    如果我想把这些方块变成按钮呢 可以嘛? 具体可以描述一下该怎么实现嘛 谢谢!

    站长回复

    按钮UIButton是UIView的子类,所以可以直接将方块(UIView)替换成按钮实现同样的动画效果。

    以第一个样例为例,可以将其中的:
    let background = UIView(frame:CGRectMake(x, y, width, width))
    background.backgroundColor = UIColor.darkGrayColor()
    self.view.addSubview(background)
    替换成:
    let background:UIButton = UIButton(type:.ContactAdd)
    background.frame=CGRectMake(x, y, width, width)
    self.view.addSubview(background)