以前在学 CAEmitterLayer 的时候,晚上的教程大多数都是烟花、火焰之类的效果。以后闲下来以后去尝试了一下实现其余的效果。bash
接触过 CAEmitterLayer 的都知道,这玩意参数很是多。实现黑洞效果用到的参数主要有这几个:ide
// 发射源形状,咱们这里用到的是圆形
emitterShape = kCAEmitterLayerCircle
/**
kCAEmitterLayerPoint; // 点
kCAEmitterLayerLine; // 直线
kCAEmitterLayerRectangle; // 矩形
kCAEmitterLayerCircle; // 圆形
kCAEmitterLayerCuboid; // 3D 矩形
kCAEmitterLayerSphere; // 3D 圆形
**/
// 发射模式,这里用的是在发射源边上发射,既圆形边上
emitterMode = kCAEmitterLayerOutline
/**
kCAEmitterLayerPoints; // 顶点
kCAEmitterLayerOutline; // 轮廓,即边上
kCAEmitterLayerSurface; // 表面,即图形的面积内
kCAEmitterLayerVolume; // 容积,即3D图形的体积内
**/
复制代码
完整代码:动画
import UIKit
class EmitterView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupUI() {
let emitterLayer = CAEmitterLayer()
emitterLayer.frame = bounds
emitterLayer.emitterPosition = center
emitterLayer.emitterSize = bounds.size
emitterLayer.emitterShape = kCAEmitterLayerCircle //发射器形状
emitterLayer.emitterMode = kCAEmitterLayerOutline
layer.addSublayer(emitterLayer)
let cell = CAEmitterCell()
cell.contents = #imageLiteral(resourceName: "circle_white").cgImage
cell.birthRate = 50 // 粒子产生数量
cell.lifetime = 10.0 // 粒子存活时间
cell.scale = 0.25 //缩放比例
cell.scaleRange = 0.1
cell.scaleSpeed = 0.025
cell.velocity = 50 //粒子的速度
cell.velocityRange = 50 //粒子的速度范围
cell.color = UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 1).cgColor
cell.redRange = 1 // 颜色变化
cell.greenRange = 1
cell.blueRange = 1
cell.alphaRange = 0.8
cell.alphaSpeed = -0.1 // 透明速度(逐渐消失)
emitterLayer.emitterCells = [cell]
}
}
复制代码
这个时候运行效果是这样子的:ui
这个时候看起来有那么一丁点相识,但仔细看的话只是粒子从小到大缩放而已,这是一个没有灵魂的黑洞。这其实还少了一个参数 preservesDepth = true
加上这个以后粒子发射就有了立体效果:spa
最后一步就是经过 CABasicAnimation 作一个绕z轴缓慢旋转的动画code
let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
rotateAnimation.fromValue = 0
rotateAnimation.toValue = Float.pi * 2
rotateAnimation.duration = 60
rotateAnimation.repeatCount = .greatestFiniteMagnitude
layer.add(rotateAnimation, forKey: nil)
复制代码
至此就达到了文章开头的效果: orm