iOS 动画 Animation-0-10:CALayer十则示例-CAEmitterLayer

iOS 动画 Animation

Posted by FishYan on September 1, 2016

iOS 动画 Animation-0-10:CALayer十则示例-CAEmitterLayer

CAEmitterLayer

CAEmitterLayer渲染的动画粒子是CAEmitterCell实例。CAEmitterLayer和CAEmitterCell都包含可调整渲染频率、大小、形状、颜色、速率以及生命周期的属性。示例如下:

import UIKit
  
class ViewController: UIViewController {
  
  // 1
  let emitterLayer = CAEmitterLayer()
  let emitterCell = CAEmitterCell()
  
  // 2
  func setUpEmitterLayer() {
    emitterLayer.frame = view.bounds
    emitterLayer.seed = UInt32(NSDate().timeIntervalSince1970)
    emitterLayer.renderMode = kCAEmitterLayerAdditive
    emitterLayer.drawsAsynchronously = true
    setEmitterPosition()
  }
  
  // 3
  func setUpEmitterCell() {
    emitterCell.contents = UIImage(named: "smallStar")?.CGImage
  
    emitterCell.velocity = 50.0
    emitterCell.velocityRange = 500.0
  
    emitterCell.color = UIColor.blackColor().CGColor
    emitterCell.redRange = 1.0
    emitterCell.greenRange = 1.0
    emitterCell.blueRange = 1.0
    emitterCell.alphaRange = 0.0
    emitterCell.redSpeed = 0.0
    emitterCell.greenSpeed = 0.0
    emitterCell.blueSpeed = 0.0
    emitterCell.alphaSpeed = -0.5
  
    let zeroDegreesInRadians = degreesToRadians(0.0)
    emitterCell.spin = degreesToRadians(130.0)
    emitterCell.spinRange = zeroDegreesInRadians
    emitterCell.emissionRange = degreesToRadians(360.0)
  
    emitterCell.lifetime = 1.0
    emitterCell.birthRate = 250.0
    emitterCell.xAcceleration = -800.0
    emitterCell.yAcceleration = 1000.0
  }
  
  // 4
  func setEmitterPosition() {
    emitterLayer.emitterPosition = CGPoint(x: CGRectGetMidX(view.bounds), y: CGRectGetMidY(view.bounds))
  }
  
  func degreesToRadians(degrees: Double) -> CGFloat {
    return CGFloat(degrees * M_PI / 180.0)
  }
  
  override func viewDidLoad() {
    super.viewDidLoad()
  
    // 5
    setUpEmitterLayer()
    setUpEmitterCell()
    emitterLayer.emitterCells = [emitterCell]
    view.layer.addSublayer(emitterLayer)
  }
  
  // 6
  override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
    setEmitterPosition()
  }
  
}

以上代码解析:

  • 1.创建粒子发射器图层和粒子胞(Creates an emitter layer and cell.)。

  • 2.按照下方步骤设置粒子发射器图层:

    为随机数生成器提供种子,随机调整粒子胞的某些属性,如速度。

    在图层背景色和边界之上按renderMode指定的顺序渲染粒子胞。

注:渲染模式默认为无序(unordered),其他模式包括旧粒子优先(oldest first),新粒子优先(oldest last),按z轴位置从后至前(back to front)还有叠加式渲染(additive)。

由于粒子发射器需要反复重绘大量粒子胞,设drawsAsynchronously为true会提升性能。

然后借助第四条中会提到的辅助方法设置发射器位置,这个例子有助于理解把drawsAsynchronously设为true为何能够提升性能和动画流畅度。

  • 3.这段代码设了不少东西。

    配置粒子胞,设内容为图片(图片在图层演示项目中)。

    指定初速及其变化量范围(velocityRange),发射器图层利用上面提到的随机数种子创建随机数生成器,在范围内产生随机值(初值+/-变化量范围),其他以“Range”结尾的相关属性的随机化规则类似。

    设颜色为黑色,使自变色(variance)与默认的白色形成对比,白色形成的粒子亮度过高。

    利用随机化范围设置颜色,指定自变色范围,颜色速度值表示粒子胞生命周期内颜色变化快慢。

    接下来这几行代码指定粒子胞分布范围,一个全圆锥。设置粒子胞转速和发射范围,发射范围emissionRange属性的弧度值决定粒子胞分布空间。

    设粒子胞生命周期为1秒,默认值为0,表示粒子胞不会出现。birthRate也类似,以秒为单位,默认值为0,为使粒子胞显示出来,必须设成正数。

    最后设xy加速度,这些值会影响已发射粒子的视角。

  • 4.把角度转换成弧度的辅助方法,还有设置粒子胞位置为视图中点。

  • 5.设置发射器图层和粒子胞,把粒子胞添加到图层,然后把图层添加到视图结构树。

  • 6.iOS 8的新方法,处理当前设备形态集(trait collection)的变化,比如设备旋转。不熟悉形态集的话可以参阅iOS 8教程。

总算说完了!信息量很大,但相信各位聪明的读者可以高效吸收。

上述代码运行效果如下:

图层演示应用中,你可以随意调节很多属性:

恭喜,看完十则示例和各种图层子类,CALayer之旅至此告一段落。

但现在才刚刚开始!新建一个项目,或者打开已有项目,尝试利用图层提升性能或营造酷炫效果!实践出真知。