一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

Swift沿路径运动的动画实现圆形、曲线、直线等路径轨迹

时间:2022-06-25 23:40:01 编辑:袖梨 来源:一聚教程网

通常要实现沿着复杂路径的动画,我们可以借助关键帧动画(CAKeyframeAnimation)来实现。由于 CAKeyframeAnimation 提供了的便利的 path 属性,我们只需要对其设置相应的路径即可。

1,准备工作

首先我们在页面上添加一个橙色的方块,后面通过对这个方块添加轨迹动画来演示CAKeyframeAnimation的使用。


import UIKit
 
class ViewController: UIViewController { 
 
    var square:UIView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        square = UIView(frame:CGRectMake(0, 0, 20, 20))
        square.backgroundColor = UIColor.orangeColor()
        self.view.addSubview(square)
    }
 
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

2,做圆周运动

下面样例中方块会沿着圆形的轨迹做圆周运动(只播放一次)
(1)通过 CGPathCreateWithEllipseInRect() 方法,我们创建一个圆形的 CGPath 作为我们的关键帧动画的 path。
(2)将 calculationMode 设置为 kCAAnimationPaced,让 Core Animation 向被驱动的对象施加一个恒定速度,不管路径的各个线段有多长。


let centerX = view.bounds.size.width/2
let boundingRect:CGRect = CGRectMake(centerX-75, 50, 150, 150)
 
let orbit = CAKeyframeAnimation(keyPath:"position")
orbit.duration = 3
orbit.path = CGPathCreateWithEllipseInRect(boundingRect,nil)
orbit.calculationMode = kCAAnimationPaced
 
square.layer.addAnimation(orbit,forKey:"Move")

3,让图层保持显示动画执行后的状态

默认情况下动画执行完毕后,图形会恢复到动画执行前的状态。比如上面样例,方块移动一周后又会跑到页面坐上角位置。如果想让方块保持显示动画执行后的状态,有如下两种方式:
(1)动画下方代码直接设置方块最终位置坐标


let centerX = view.bounds.size.width/2
let boundingRect:CGRect = CGRectMake(centerX-75, 50, 150, 150)
 
let orbit = CAKeyframeAnimation(keyPath:"position")
orbit.duration = 3
orbit.path = CGPathCreateWithEllipseInRect(boundingRect,nil)
orbit.calculationMode = kCAAnimationPaced
square.layer.addAnimation(orbit,forKey:"Move")
 
//下面代码让方块运动一周后停留在终点位置(否则会回到原来的位置)
square.layer.position = CGPointMake(centerX+75, 125)

(2)将动画的 removedOnCompletion 属性那就设置为false,fillMode 设置为 kCAFillModeForwards。

let centerX = view.bounds.size.width/2
let boundingRect:CGRect = CGRectMake(centerX-75, 50, 150, 150)
 
let orbit = CAKeyframeAnimation(keyPath:"position")
orbit.duration = 3
orbit.path = CGPathCreateWithEllipseInRect(boundingRect,nil)
orbit.calculationMode = kCAAnimationPaced
orbit.removedOnCompletion = false
orbit.fillMode = kCAFillModeForwards
 
square.layer.addAnimation(orbit,forKey:"Move")

4,在轨迹上重复运动
repeatCount 参数可以设置动画的重复次数,将其设为 HUGE 可以让方块圆周运动动画一直循环播放下去。

let centerX = view.bounds.size.width/2
let boundingRect:CGRect = CGRectMake(centerX-75, 50, 150, 150)
        
let orbit = CAKeyframeAnimation(keyPath:"position")
orbit.duration = 3
orbit.path = CGPathCreateWithEllipseInRect(boundingRect,nil)
orbit.calculationMode = kCAAnimationPaced
orbit.repeatCount = HUGE
        
square.layer.addAnimation(orbit,forKey:"Move")

5,让方块沿着路径旋转

设置 rotationMode 属性为 kCAAnimationRotateAuto 可以让方块沿着路径旋转,即方块不管移动到哪个位置,它始终朝向圆心。


let centerX = view.bounds.size.width/2
let boundingRect:CGRect = CGRectMake(centerX-75, 50, 150, 150)
        
let orbit = CAKeyframeAnimation(keyPath:"position")
orbit.duration = 3
orbit.path = CGPathCreateWithEllipseInRect(boundingRect,nil)
orbit.calculationMode = kCAAnimationPaced
orbit.repeatCount = HUGE
orbit.rotationMode = kCAAnimationRotateAuto
        
square.layer.addAnimation(orbit,forKey:"Move")

6,构建更加复杂的路径

通过 CGPathCreateMutable,我们可以将多条弧线、直线等拼接成一个复杂的路径,让方块在这个路径上运动。


let centerX = view.bounds.size.width/2
//创建用于转移坐标的Transform,这样我们不用按照实际显示做坐标计算
var transform:CGAffineTransform = CGAffineTransformMakeTranslation(centerX, 50);
let path =  CGPathCreateMutable()
CGPathMoveToPoint(path, &transform, 0, 0);
CGPathAddLineToPoint(path, &transform, 0, 75);
CGPathAddLineToPoint(path, &transform, 75, 75);
CGPathAddArc(path, &transform, 0, 75, 75, 0, CGFloat(1.5 * M_PI), false);
      
let orbit = CAKeyframeAnimation(keyPath:"position")
orbit.duration = 3
orbit.path = path
orbit.calculationMode = kCAAnimationPaced
orbit.repeatCount = HUGE
//orbit.rotationMode = kCAAnimationRotateAuto
        
square.layer.addAnimation(orbit,forKey:"Move")


7,使用动画组实现多种动画的组合

通过动画组(CAAnimationGroup),我们可以将多个动画组合在一起同时播放。
下面的样例中,小方块沿着轨迹运动的同时,自身还会快速地旋转。(方块移动一周,自身会旋转100次)


//旋转动画
let rotateAnimation =  CAKeyframeAnimation(keyPath:"transform.rotation.z")
rotateAnimation.values = [0,200*M_PI]
 
//轨迹动画路径
let centerX = view.bounds.size.width/2
//创建用于转移坐标的Transform,这样我们不用按照实际显示做坐标计算
var transform:CGAffineTransform = CGAffineTransformMakeTranslation(centerX, 50);
let path =  CGPathCreateMutable()
CGPathMoveToPoint(path, &transform, 0, 0);
CGPathAddLineToPoint(path, &transform, 0, 75);
CGPathAddLineToPoint(path, &transform, 75, 75);
CGPathAddArc(path, &transform, 0, 75, 75, 0, CGFloat(1.5 * M_PI), false);
 
//轨迹动画
let orbitAnimation = CAKeyframeAnimation(keyPath:"position")
orbitAnimation.path = path
orbitAnimation.calculationMode = kCAAnimationPaced
 
//组合两个动画
let animationgroup =  CAAnimationGroup()
animationgroup.animations = [rotateAnimation, orbitAnimation]
animationgroup.duration = 4
animationgroup.repeatCount = HUGE
square.layer.addAnimation(animationgroup,forKey:"Move")

原文出自:http://www.hangge.com/blog/cache/detail_1072.html

热门栏目