之前在學 CAEmitterLayer 的時候,晚上的教程大多數都是煙花、火焰之類的效果。之後閒下來之後去嘗試了一下實現其他的效果。
接觸過 CAEmitterLayer 的都知道,這玩意引數非常多。實現黑洞效果用到的引數主要有這幾個:
// 發射源形狀,我們這裡用到的是圓形
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]
}
}
複製程式碼
這個時候執行效果是這樣子的:
這個時候看起來有那麼一丁點相識,但仔細看的話只是粒子從小到大縮放而已,這是一個沒有靈魂的黑洞。這其實還少了一個引數
preservesDepth = true
加上這個之後粒子發射就有了立體效果:
最後一步就是通過 CABasicAnimation 做一個繞z軸緩慢旋轉的動畫
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)
複製程式碼
至此就達到了文章開頭的效果: