Swift实现黑洞(漩涡)效果

之前在学 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)

至此就达到了文章开头的效果:

猜你喜欢

转载自juejin.im/post/5af3dea1518825670c45f2d1