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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容