这篇教程将一起学习使用CAEmitterCell
和CAEmitterLayer
,最后做出一个仿微信表情雨的效果。
开发环境:Swift 3.0 + Xcode 8.2
先看最终效果:
CAEmitterCell
定义了一种粒子的原型,然后通过CAEmitterLayer
对象发射这些粒子。一种粒子原型包括了设定其方向和粒子发射属性。粒子原型本身还可以包含子粒子(sub-cells),以实现其本身再将子粒子发射出去的效果。在效果图中,每一个🍩便是由CAEmitterCell
定义的。我们需要设定的值看代码(当然还有别的值,代码中给出的只是一小部分)。
CAEmitterLayer
是CALayer
的子类,定义了发射粒子的动画图层。粒子是被渲染在此图层上的。如果说CAEmitterCell
是子弹,那CAEmitterLayer
就是那把枪了。
代码比较简单,直接上。
let cell = CAEmitterCell()
cell.name = "laughing" // 后面的KVC会用到
cell.contents = "🍩".cgImage // 图层内容
cell.birthRate = 10.0 // 粒子的每秒的产出速率
cell.lifetime = 10.0 // 显示时长
cell.velocity = -80 // 速度,向下为负
cell.velocityRange = -40 // 速度变化区间
cell.yAcceleration = 45 // y轴上的加速度
cell.emissionRange = .pi / 8 // 发射角度变化区间
let emitterLayer = CAEmitterLayer()
emitterLayer.frame = CGRect(x: 0, y: 0, width: view.bounds.size.width, height: 20)
emitterLayer.emitterSize = CGSize(width: view.bounds.size.width, height: 0)
emitterLayer.emitterPosition = CGPoint(x: view.bounds.size.width / 2, y: -40)
emitterLayer.emitterMode = kCAEmitterLayerOutline // 发射样式,这里指围绕发射器的外轮廓发射
emitterLayer.emitterShape = kCAEmitterLayerLine // 发射器的形状,可以是线形、圆形、方形等
emitterLayer.emitterCells = [cell] // 传入粒子对c象
view.layer.addSublayer(emitterLayer)
如何暂停呢?直接cell.birthRate = 0
是停不下来的,我们需要用KVC:emitterLayer.setValue(0.0, forKeyPath: "emitterCells.laughing.birthRate")
。
CALayer
的content
是一个Any?
,实际上要传入的是一个CGImage
对象。为了使emoji表情也能变成一个CGImage
,我稍微给String
加了个extension。正好复习一下UIGraphicsBeginImageContextWithOptions
那几个API。
extension String {
// 将字符串以CGImage显示
var cgImage: CGImage? {
let textAttri: [String: Any]? = [NSFontAttributeName: UIFont.systemFont(ofSize: 16)]
UIGraphicsBeginImageContextWithOptions(self.size(attributes: textAttri), false, 0)
defer { UIGraphicsEndImageContext() }
self.draw(at: .zero, withAttributes: textAttri)
let image = UIGraphicsGetImageFromCurrentImageContext()
return image?.cgImage
}
}
大功告成。附上源码:https://github.com/Hesse-Huang/CAEmitterCellLearning
最后有个小问题,就是每次点击Button时有几个粒子直接出现,而不是在屏幕上边缘落下。如果知道如何解决的同学请留言评论哦,谢谢~