
圣诞节一直是一年中我最喜欢的时间之一。 对我来说,圣诞节是一个充满爱,欢笑,幸福和其他神奇事物的季节。
我在西班牙出生和成长,尤其是在特内里费岛,特内里费岛是一个阳光明媚的亚热带岛屿,就在非洲海岸附近的大西洋中间。 我必须说,特内里费岛的圣诞节与自加入Badoo以来在伦敦度过的最近两个圣诞节有很大不同。
在伦敦生活的一个奇妙之处在于,我有生以来第一次看到雪,真正的雪花从天上掉下来。 太不可思议了!
谈到雪花,我有一个有趣的故事,向您介绍去年圣诞节那天在办公室发生的事。 就在我回家特内里费岛与家人度过几天之前。
碰巧的是,去年12月,我被分配了一张非常有趣的机票,内容如下

嗯,非常有趣。 Badoo希望为我们的iOS应用程序创建一个圣诞节动画,其中包括雪花,我很幸运能得到这份工作,我喜欢这个主意! 但是我不知道从哪里开始。
像往常一样,有一个素描文件链接到我的票证,幸运的是,还有一个外观如下的设计:

因此,至少我知道我们想要什么,但是我不确定这些雪花到底是什么。 我去了设计团队了解更多。
正如我所怀疑的那样,他们已经使用
“ After Effects”构建了一个惊人的动画版本。
基本上,他们告诉我,这个想法是添加动画雪花,该雪花将在现有应用启动动画期间从屏幕顶部掉落(他们还希望看到徽标中添加了圣诞老人的帽子,但作为简单的资产替换,它不会t本文中的数字)。
我知道iOS的启动动画使用了
Lottie,因为我在实现它之前已经去过一段时间了(有关该细节的更多信息,请查看
Radek Cieciwa的这篇
文章 。但是,我告诉设计师我会考虑一些想法,因为也许有一种无需使用Lottie即可添加雪花的简单方法,我开始研究各种不同的方法。
这是Radek实施的Badoo中的启动动画。 干净!

这是我在上面制作的雪花动画。 想知道我是怎么做到的吗? 继续阅读。

粒子系统
阅读了一些有趣的动画文档后,我被提醒“粒子系统”是在电影和视频游戏中实现这种动画的一种常用技术。
维基百科完美地描述了这一点:
“粒子系统是游戏物理学,运动图形和计算机图形学中的一种技术,它使用大量非常小的精灵,3D模型或其他图形对象来模拟某些种类的“模糊”现象,否则很难做到这一点。使用传统的渲染技术进行复制-通常是高度混乱的系统,自然现象或由化学反应引起的过程。”
这项技术是在1982年的电影《星际迷航II:可汗的愤怒》中引入的,目的是创造虚构的《创世纪》效果。
粒子系统由一个或多个单独的图形图元组成,例如点,线或称为粒子的图像。 这些粒子由粒子系统显示/发射。
这些粒子中的每一个都具有直接或间接影响粒子行为的属性,并定义了渲染粒子的方式和位置。 它们可以大量移动并沿不同方向移动,以产生流畅的效果。
当粒子由其粒子系统生成或发射时,动画将生效。 该系统在其自身区域内的任意位置发射粒子。 该区域可以具有不同的形状,例如圆形,长方体,直线,点,矩形,球形等。
该系统还定义了一些影响其几何形状,生成速度和其他方面的属性。 对于用于粒子发射器系统的每个API,都有相似的行为使用不同的属性名称。
当粒子系统同时发射所有这些图像时,它会创建令人惊叹的动画,看起来像雨,火甚至是雪!



动手
我猜想苹果可能会在某些API中提供对粒子系统的支持。 我检查了,是的,我是对的!
该粒子系统是iOS中“核心动画”的一部分,我在
CAEmitterLayer和
CAEmitterCell中找到了关于它的很好的文档。
一旦获得了有关iOS中粒子系统和受支持的API的所有信息,就可以开始我最喜欢的部分,实际上是为我的雪花动画实现代码。
可悲的是,圣诞节并不会永远持续下去,因此需要对其进行远程控制,以便可以在12月25日之后将其删除。
如前所述,应用启动动画是在Lottie中实现的。 然后,我必须弄清楚如何在不破坏现有代码的情况下将雪花添加到现有动画中,因为在发行后不久必须将其删除。
我找到了一种非常简单的方法。 我将注入一个新的透明UIView,以在徽标动画和背景之间显示雪花动画,然后使用远程标志控制此视图的外观。

上面的图像显示了最终动画中使用的视图。
- 包含粒子系统动画的视图 ; 基本上,雪花
- 用于制作徽标动画的视图 :使用Lottie进行动画处理的视图 。
解决此问题后,我只需要创建一个可重用的UIView类,其中包含粒子发射器的逻辑即可生成令人难以置信的动画雪花。
我首先需要的是用于表示实际雪花的单元发射器内容的图像资产。 但是它们很简单,对吧?
每个雪花只是一个大的白色圆圈,再加上另一个大的模糊白色圆圈。 我是使用Sketch自己创建的。

一些实施细节
CAEmitterLayer是一种特殊的CALayer,可以发射,设置动画和渲染粒子系统。 它具有一些属性,可以自定义图层的几何形状,定位和渲染模式等。
我通过创建发射器层开始动画:
let snowEmitterLayer.emitterShape = CAEmitterLayerEmitterShape.line snowEmitterLayer.beginTime = CACurrentMediaTime() snowEmitterLayer.timeOffset = 10.0
我只需要三个属性即可设置我的图层:
- itterShape :定义层的形状。 就我而言,我使用线性形状是因为它可以使雪花在所有屏幕上右移
- timeOffset :所需的效果是从动画开始就立即在整个屏幕上看到雪花。 此属性是CAMedia Timing协议的一部分,并且基本上像动画的快进一样起作用。 我将其设置为10.0秒,可以有效地快进动画并用雪花覆盖屏幕(如果我将其设置为0.0秒,则雪花将从顶部开始缓慢下落,并且需要花费一些时间才能覆盖整个雪花屏幕。
准备好发射极层之后,我创建了2个不同的发射极单元。 第一个代表圆形的“较重”雪花,另一个代表“较轻”的雪花。
对于“较重”的雪花效果,我使用了此发射器单元:
let flakeEmitterCell = CAEmitterCell() flakeEmitterCell.contents = UIImage(named: "snowflake_dot")!.cgImage flakeEmitterCell.emissionRange = .pi flakeEmitterCell.lifetime = 20.0 flakeEmitterCell.birthRate = 30 flakeEmitterCell.scale = 0.15 flakeEmitterCell.scaleRange = 0.6 flakeEmitterCell.velocity = 30.0 flakeEmitterCell.velocityRange = 20 flakeEmitterCell.spin = -0.5 flakeEmitterCell.spinRange = 1.0 flakeEmitterCell.yAcceleration = 30.0 flakeEmitterCell.xAcceleration = 5.0
如您所见,我必须为单元设置许多属性,所有这些属性都很重要,以实现所需的视觉效果。
- content:用于表示雪花的CGImage。 在这种情况下,它只是上面“动手操作”部分所述的资产之一
- missionRange :以弧度定义角度,定义围绕发射角度的圆锥。 我将PI设置为允许粒子以任何角度在屏幕上可见
- 寿命 :定义细胞/粒子应该存活多少秒
- birthRate :定义每秒由发射器层生成的这种特定粒子类型的数量
- scale和scaleRange :设置应有多大的粒子,1.0是最大大小。 该范围定义了由发射器单元同时创建的粒子之间大小的变化,从而允许使用不同大小的随机单元
- velocity和velocityRange :定义像元的初始速度。 这在velocityRange属性指定的范围内随机变化
- spin和spinRange :这些定义旋转速度,以弧度/秒为单位,并在spinRange属性指定的范围内以随机量变化
- yAcceleration和xAcceleration :应用于单元的加速度矢量的分量
我还需要第二个发射器来创建柔软的雪花。 对于此发射器,我要做的就是为所有属性设置相同的值,但以下两个除外:
- 内容 :在这种情况下,它将是巨大的,模糊的圆形图像资产
- 速度 :为了模拟更轻的雪花,我放慢了“下降”速度
let blurryFlakeEmitterCell = CAEmitterCell() blurryFlakeEmitterCell.contents = UIImage(named: "snowflake_blurry_dot")?.cgImage blurryFlakeEmitterCell.velocity = 40 ...
其余的非常简单,我只需要将图层和单元链接在一起。 结果!
snowEmitterLayer.emitterCells = [flakeEmitterCell, blurryFlakeEmitterCell] self.layer.addSublayer(snowEmitterLayer)
结论
很快,我就为雪花动画找到了一个可行的Badoo解决方案,并且最终结果看起来非常不错。 我以简单干净的实现方式回到了设计师手中,他们喜欢它。
只要您拥有正确的工具,使用粒子系统创建的动画就可以给人留下深刻的印象,并且相对易于实施。
有关粒子发射器的扩展信息