PK创意闹新春,我正在参加「春节创意投稿大赛」,详情请看:春节创意投稿大赛

前言

马上就要过年了,在这里提前祝大家新年快乐。还记得小时候放鞭炮、放烟花的快乐时光吗,在大城市里面不让放烟花,就算在农村,有的地方也不让放了swifter。现在我们就使用ARKit+CAEmitterLayer粒子发射器给大家放个烟花吧。

使用ARKit+CAEmitterLayer粒子发射器放个烟花

下面我们就来实现这个效果:

1、创建AR项目

1.1、 打开XCode,新建项目,选择Augmented Reality App

使用ARKit+CAEmitterLayer粒子发射器放个烟花

1.2、设置项目名称,bundlswift怎么读e id,选择渲染引擎SceneKit,语言使用Swift

使用ARKit+CAEmitterLayer粒子发射器放个烟花

创建完成之后,你会发现系统自动创建了一个飞机的场景

class ViewController: UIViewController, ARSCNViewDelegate {
  @IBOutlet var sceneView: ARSCNView!
  override func viewDidLoad() {
    super.viewDidLoad()
    // Set the view's delegate
    sceneView.delegate = self
   
    // Show statistics such as fps and timing information
    sceneView.showsStatistics = true
   
    // Create a new scene
    let scene = SCNScene(named: "art.scnassets/ship.scn")!
   
    // Set the scene to the view
    sceneView.scene = scene
  }
 
    // 其他代码省略...
}

1.3、将飞机的场景删除,然后创建一个平面几何形状SCNPlane

override func viewDidLoad() {
    super.viewDidLoad()
    // Set the view's delegate
    sceneView.delegate = self
    // 创建一个平面几何形状SCNPlane 宽为0.5米,高为1米
    let plane = SCNPlane(width: 0.5, height: 1)
    // 基于几何图形创建节点,节点的创建不仅仅可以基于平面,长方体、圆球、圆锥、圆环、金字塔形 等等都可以创建
    let node = SCNNode(geometry: plane)
    node.position = SCNVector3Make(0, 0.1, -1)
    // 添加节点
    sceneView.scene.rootNode.addChildNode(node)
}

这样一个平面场景就创建好了,下面看看效果:

使用ARKit+CAEmitterLayer粒子发射器放个烟花

2、CAEmitterLayer粒子发射器实现烟花

实现烟花效果,我们需要使用CAEmitterLswifterayer结合CAEmitterCell。烟花需要三个cell,一个提供发射的,一个用于爆炸的,一个用于爆炸后飞溅的火花

下面是代码:

extension ViewController {
  // 烟花View
  private func createFireWorksView() -> UIView {
    let fireworksBgView = UIView()
        fireworksBgView.isOpaque = false
    fireworksBgView.frame = CGRect(x: 0, y: 0, width: 500, height: 1000)
    let viewSize = fireworksBgView.bounds.size
   
    // 设置CAEmitterLayer
    let fireworksEmitter = CAEmitterLayer()
    fireworksEmitter.preservesDepth = true
    // 1、设置发射的位置
    fireworksEmitter.emitterPosition = CGPoint(x: viewSize.width/2, y: viewSize.height)
    // 发射源的size 决定了发射源的大小
    fireworksEmitter.emitterSize = CGSize(width: viewSize.width/2, height: 0)
    // 发射模式
    fireworksEmitter.emitterMode = .outline
    // 发射形状
    fireworksEmitter.emitterShape = .line
    // 渲染模式
    fireworksEmitter.renderMode = .additive
    // 用于初始化随机函数的种子
    fireworksEmitter.seed = arc4random()%100 + 1
    // 每秒产生的粒子数量的系数
    fireworksEmitter.birthRate = 1
    // 2、发射
    let rocket = CAEmitterCell()
    // 粒子参数的速度乘数因子
    rocket.birthRate = 1
    // 发射角度
    rocket.emissionRange = 0
    // 速度
    rocket.velocity = 500
    // 速度范围
    rocket.velocityRange = 100
    // y方向的加速度分量
    rocket.yAcceleration = 70
    rocket.lifetime = 1.02
    // 粒子要展示的图片
    rocket.contents = UIImage(named: "01")?.cgImage
    // 缩放比例
    rocket.scale = 1
    // 粒子颜色
    rocket.color = UIColor.red.cgColor
    rocket.greenRange = 1
    rocket.redRange = 1
    rocket.blueRange = 1
    // 粒子旋转角度范围
    rocket.spinRange = 0
    // 3、爆炸
    let burst = CAEmitterCell()
    // 粒子参数的速度乘数因子
    burst.birthRate = 1.0
    // 速度
    burst.velocity = 10
    burst.scale = 1
    burst.redSpeed = -1.5
    burst.blueSpeed = 1.5
    burst.greenSpeed = 1.0
    burst.lifetime = 0.1
    // 4、爆炸后飞溅的火花
    let spark = CAEmitterCell()
    spark.birthRate = 400
    spark.velocity = 300
    spark.emissionRange = 2 * CGFloat.pi
    spark.yAcceleration = 200
    // 生命周期范围
    spark.lifetime = 1.5
    // 粒子内容
    spark.contents = UIImage(named: "01")?.cgImage
    spark.scaleSpeed = -0.4
    spark.greenSpeed = -0.1
    spark.redSpeed = 0.4
    spark.blueSpeed = -0.1
    spark.alphaSpeed = -0.25
    spark.spin = 2 * CGFloat.pi
    spark.spinRange = 2 * CGFloat.pi
    // 粒子添加到CAEmitterLayer上
    fireworksEmitter.emitterCells = [rocket]
    rocket.emitterCells = [burst]
    burst.emitterCells = [spark]
    fireworksBgView.layer.addSublayer(fireworksEmitter)
    return fireworksBgView
  }
}

3、创建SCNMaterial渲染器,将烟花View添加到里面

以下代码都是在 1.3 步里application

3.1、创建渲染器

// 创建渲染器
let material = SCNMaterial()
// 将`烟花View`设置给contents,这个 contents 属性可以设置很多东西,UILabel,UIImage,甚至 AVPlayer 都可以
material.diffuse.contents = createFireWorksView()

3.2、用渲染器对几何图形进swift系统行渲染

// 用渲染器对几何图形进行渲染
node.geometry?.materials = [material]

到此整个功能就结束了,demo地址

参考:
CAEmitterLayer粒子发射器的神奇效果