iOS动画指南 - 5.下雪的粒子效果、帧动画

1 .粒子发射器: CAEmitterLayer

CAEmitterLayer是核心动画中的一个类,用它可以很原生的创造微粒效果.每一个微粒就是一个CAEmitterCell对象,我们可以不用太过关心cell的创建与销毁.只要我们设置好参数,这些系统会帮我们完成.

话不多说,上代码:

        // 创建CAEmitterLayer 并设置好CAEmitterLayer
        let emitter = CAEmitterLayer()
        let rect = CGRect(x: 0.0, y: 100.0, width: view.bounds.width, height: 100)
        emitter.backgroundColor = UIColor.blackColor().CGColor
        emitter.frame = rect
        view.layer.addSublayer(emitter)
        
        // 所有粒子随机出现在所给定的矩形框内
        emitter.emitterShape = kCAEmitterLayerRectangle
        // 设置位置大小
        emitter.emitterPosition = CGPoint(x: rect.width/2, y: rect.height/2)
        emitter.emitterSize = rect.size
        
        // 一个cell代表一个微粒
        let emitterCell = CAEmitterCell()
        emitterCell.contents = UIImage(named: "flake")!.CGImage

        // 每秒出现的比率 cell的生命周期
        emitterCell.birthRate = 8
        emitterCell.lifetime = 3
        emitter.emitterCells = [emitterCell]

emitter的emitterShape属性:
常用到的有三种:

  • kCAEmitterLayerPoint 将所有的粒子集中在position的位置,可用来做火花爆炸效果
  • kCAEmitterLayerLine 所有的粒子位于一条线上,可用来作瀑布效果,下雪效果
  • kCAEmitterLayerRectangle 所有粒子随机出现在所给定的矩形框内

在上面代码的基础上,在添加下面的:

        // x y 轴的加速度
        emitterCell.yAcceleration = 70.0
        emitterCell.xAcceleration = 70.0
        // 初始速度
        emitterCell.velocity = 20.0
        // 发射角度
        emitterCell.emissionLatitude = CGFloat(M_PI_2)

上面的CAEmitterLayer设置的属性基本都是固定的值,如果我们要实现一个下雪效果,需要很多随机的属性,这些都有:

    func snow() {
        
        
        // 通过CAEmitterLayer可以很原生的创造微粒效果,不需要第三方库
        let emitter = CAEmitterLayer()
        let rect = CGRect(x: 0.0, y: -100.0, width: view.bounds.width, height: view.bounds.height+100)
        //        let rect = view.bounds
        emitter.backgroundColor = UIColor.blackColor().CGColor
        emitter.frame = rect
        view.layer.addSublayer(emitter)
        
        // kCAEmitterLayerPoint 将所有的粒子集中在position的位置,可用来做火花爆炸效果
        // kCAEmitterLayerLine 所有的粒子位于一条线上,可用来作瀑布效果
        // kCAEmitterLayerRectangle 所有粒子随机出现在所给定的矩形框内
        emitter.emitterShape = kCAEmitterLayerLine
        emitter.emitterPosition = CGPoint(x: rect.width/2, y: 0)
        emitter.emitterSize = rect.size
        
        // 一个cell代表一个微粒
        let emitterCell = CAEmitterCell()
        emitterCell.contents = UIImage(named: "flake3")!.CGImage
        
        // 每秒创建的cell
        emitterCell.birthRate = 250
        // cell的生命周期为1.5秒
        //        emitterCell.lifetime = 10
        // emitter可以添加很多不同类型的cell
        emitter.emitterCells = [emitterCell]
        
        // 制造一个y轴的加速度
        emitterCell.yAcceleration = 70.0
        // 制造一个x轴的加速度
        emitterCell.xAcceleration = 10.0
        
        //        emitterCell.velocity = 20.0
        // 给微粒设置一个发射角度
        emitterCell.emissionLongitude = CGFloat(-M_PI)
        //        emitterCell.scale = 0.8
        
        
        
        // 添加随机的速度,如果有velocity,那么范围为 -180 ~ 220
        emitterCell.velocityRange = 200.0
        emitterCell.emissionRange = CGFloat(M_PI_2)
        
        emitterCell.lifetimeRange = 18
        
        //    emitterCell.color = UIColor(red: 0.9, green: 1.0, blue: 1.0, alpha: 1.0).CGColor
        // 值为0.3 的范围为 0.7~1.3,但由于高于1算1,所以值得范围为 0.7~1
        emitterCell.redRange = 0.3
        emitterCell.greenRange = 0.3
        emitterCell.blueRange = 0.3
        // 随机大小
        emitterCell.scaleRange = 0.8
        // 每秒缩小15%
        emitterCell.scaleSpeed = -0.05
        
        emitterCell.alphaRange = 0.75
        emitterCell.alphaSpeed = -0.15

    }

2.帧动画
其实iOS上所有的动画,到最后都是转化成已帧动画的形式播放的.当然了,这种帧动画的实现肯定也会提供的.
实现的步骤:

        // 将需要添加帧动画的图片添加进去
        penguinView.animationImages = walkFrames
        // 设置播放时间
        penguinView.animationDuration = animationDuration / 3
        // 设置重复次数
        penguinView.animationRepeatCount = 3

        // 最后在一个适当的位置播放就行了
        penguinView.startAnimating()

帧动画我们实现一个小企鹅可以左右行走,并且可以在地上滑动的效果:

注:由于比较简单,我就简单的贴一下代码啦!想细看的可以找文章末尾给出的源码链接!

1.添加背景图片,以及左右移动,以及滑动按钮,并设置好按钮的监听


    // MARK: - 设置UI
    lazy var bgView : UIImageView = {
        let bgView = UIImageView(image:UIImage(named: "bg"))
        bgView.frame = self.view.bounds
        return bgView
    }()
    
    lazy var leftButton : UIButton = {
        let btn = UIButton()
        btn.setImage(UIImage(named: "btn-left"), forState: .Normal)
        btn.frame = CGRect(x: 0, y: UIScreen.mainScreen().bounds.height-100, width: 100, height: 100)
        btn.addTarget(self, action: Selector("leftBtnClick"), forControlEvents: .TouchUpInside)
       return btn
    }()
    
    lazy var rightButton : UIButton = {
        let btn = UIButton()
        btn.setImage(UIImage(named: "btn-right"), forState: .Normal)
        btn.frame = CGRect(x: 100, y: UIScreen.mainScreen().bounds.height-100, width: 100, height: 100)
        btn.addTarget(self, action: Selector("rightBtnClick"), forControlEvents: .TouchUpInside)

        return btn
    }()
    
    lazy var slideButton : UIButton = {
        let btn = UIButton()
        btn.setImage(UIImage(named: "btn-slide"), forState: .Normal)
        btn.frame = CGRect(x: UIScreen.mainScreen().bounds.width-100, y: UIScreen.mainScreen().bounds.height-100, width: 100, height: 100)
        btn.addTarget(self, action: Selector("slideBtnClick"), forControlEvents: .TouchUpInside)
        return btn
    }()
    
    lazy var penguinView : UIImageView = {
        let penguin = UIImageView()
        penguin.image = UIImage(named: "walk01")
        penguin.frame = CGRect(x: 100, y: UIScreen.mainScreen().bounds.height-175, width: self.penguinWidth , height: 96)
        return penguin
    }()

2.加载帧动画图片,设置好走路和滑行的动画,判断是否需要翻转图片

    // 添加走路动画的图片
    var walkFrames = [
        UIImage(named: "walk01.png")!,
        UIImage(named: "walk02.png")!,
        UIImage(named: "walk03.png")!,
        UIImage(named: "walk04.png")!
    ]
    // 添加滑行的图片
    var slideFrames = [
        UIImage(named: "slide01.png")!,
        UIImage(named: "slide02.png")!,
        UIImage(named: "slide01.png")!
    ]
    
    let animationDuration = 1.0
    let penguinWidth: CGFloat = 108.0
    let penguinHeight: CGFloat = 96.0

 // 走路的动画
    func loadWalkAnimation() {
        
        // 将需要添加帧动画的图片添加进去
        penguinView.animationImages = walkFrames
        // 设置播放时间
        penguinView.animationDuration = animationDuration / 3
        // 设置重复次数
        penguinView.animationRepeatCount = 3
        
    }
    // 滑行的动画
    func loadSlideAnimation() {
        penguinView.animationImages = slideFrames
        penguinView.animationDuration = animationDuration
        penguinView.animationRepeatCount = 1
    }
    
    // 判断左右 如果不是右边翻转图片
    var isLookingRight: Bool = true {
        didSet {
            let xScale: CGFloat = isLookingRight ? 1 : -1
            penguinView.transform = CGAffineTransformMakeScale(xScale, 1)
            slideButton.transform = penguinView.transform
        }
    }

3.处理按钮的点击事件

    func leftBtnClick() {
        isLookingRight = false
        penguinView.startAnimating()
        UIView.animateWithDuration(animationDuration, delay: 0.0, options: .CurveEaseOut, animations: {
            self.penguinView.center.x -= self.penguinWidth
            }, completion: nil)
    }
    
    func rightBtnClick() {
        isLookingRight = true
        penguinView.startAnimating()
        UIView.animateWithDuration(animationDuration, delay: 0.0, options: .CurveEaseOut, animations: {
            self.penguinView.center.x += self.penguinWidth
            }, completion: nil)
        
    }
    
    func slideBtnClick() {
        // 设置滑行动画
        loadSlideAnimation()        
        penguinView.startAnimating()
        UIView.animateWithDuration(animationDuration - 0.02, delay: 0.0, options: .CurveEaseOut, animations: {
            self.penguinView.center.x += self.isLookingRight ?
                self.penguinWidth : -self.penguinWidth
            }, completion: {_ in
                self.loadWalkAnimation()
        })

    }

总结:本篇主要介绍了粒子效果,以及帧动画.

本文整理自 : iOS.Animations.by.Tutorials.v2.0
源码 : https://github.com/DarielChen/DemoCode
如有疑问,欢迎留言 :-D

推荐阅读更多精彩内容