iOS开发-iOS粒子发射器开发-iOS粒子动画下雨下雪天气动画开发-CAEmitterLayer粒子发射器-CAEmitterCell粒子开发实践

时间:2024-04-04 11:21:43

本期内容:

  • CAEmitterLayer 粒子发射器(层)
  • CAEmitterCell 粒子
  • 下雨效果
  • 下雪效果
  • 烟火效果
  • 需要注意的属性叠加
  • 总结以及demo下载

CAEmitterLayer 粒子发射器(层)

简介:CAEmitterLayer是发射、动画和渲染粒子系统的层。 是CALayer的一个常用子类,CALayer的子类有很多,如果能很好的使用它们会得到一些意想不到的效果。CAEmitterLayer就是其中之一,CAEmitterLayer是用于实现基于Core Animation的粒子发生器系统。由CAEmitterCell实例定义的粒子被绘制在层的背景颜色和边框之上。

具体属性清单:
	// 常用属性:
     NSArray<CAEmitterCell *> *emitterCells; // 用来装粒子的数组
     
     CGPoint emitterPosition; 	// 决定了粒子发射形状的中心点
     CGFloat emitterZPosition;
     CGSize emitterSize; 			// 发射源的尺寸大小
     
     NSString *emitterShape; 		// 发射源的形状
     NSString *emitterMode; 		// 发射模式
     NSString *renderMode; 		// 渲染模式
     
   // 不常用属性:
     float birthRate; 			// 粒子产生系数,默认1.0 (可以在Cell里面赋值)
     float lifetime; 			// 粒子的生命周期系数, 默认1.0 (可以在Cell里面赋值)
     BOOL preservesDepth;		// 定义该层是否将其子层压平到其平面。
     CGFloat emitterDepth;		// 确定发射器形状的深度
     float velocity; 			// 粒子速度系数, 默认1.0 (可以在Cell里面赋值)
     float scale; 				// 粒子的缩放比例系数, 默认1.0 (可以在Cell里面赋值)
     float spin; 				// 粒子的自旋转速度系数, 默认1.0 (可以在Cell里面赋值)
     unsigned int seed; 		// 随机数发生器

CAEmitterLayer的使用方式如下:

    // 1.创建CAEmitterLayer
    emitterLayer = [CAEmitterLayer layer];
    
    // 2.设置CAEmitterLayer的属性(最主要的是前四个)
    // 发射源的形状 是枚举类型
    emitterLayer.emitterShape = kCAEmitterLayerLine;
    //    kCAEmitterLayerCircle
    //    粒子从一个以(发射位置)为中心的圆中发射出来。
    //    kCAEmitterLayerCuboid
    //    粒子从一个相反角的长方体(3D矩形)发射。
    //    kCAEmitterLayerLine
    //    粒子从(发射位置)沿直线发射。
    //    kCAEmitterLayerPoint
    //    粒子从一个点(发射位置)发射出来。
    //    kCAEmitterLayerRectangle
    //    粒子从一个有相对角的矩形发射。
    //    kCAEmitterLayerSphere
    //    粒子从一个以(发射位置)为中心的球体中发射出来。
    
    // 发射模式 枚举类型
    emitterLayer.emitterMode = kCAEmitterLayerSurface;
    //    kCAEmitterLayerOutline
    //    粒子从粒子发射器的轮廓发射出来。
    //    kCAEmitterLayerPoints
    //    粒子从粒子发射器上的点发射出来。
    //    kCAEmitterLayerSurface
    //    粒子从粒子发射器的表面发射出来。
    //    kCAEmitterLayerVolume
    //    粒子从粒子发射器中的a位置发射。
    
    // 发射源的size 决定了发射源的大小,如果做了倾斜或者便宜屏幕宽度是不够的,那时候就需要自定义
    emitterLayer.emitterSize = self.view.frame.size;
    // 发射源的位置
    emitterLayer.emitterPosition = CGPointMake(self.view.bounds.size.width * 0.5, -10);
    // 渲染模式 枚举类型 (⭐️这个渲染模式表达效果会很不好,不常用,kCAEmitterLayerAdditive,可以让重叠的部分高亮)
    emitterLayer.renderMode = kCAEmitterLayerAdditive;
    //  kCAEmitterLayerOldestFirst;
    //  kCAEmitterLayerOldestLast;
    //  kCAEmitterLayerBackToFront;
    //  kCAEmitterLayerAdditive;
    
    // 3.添加到目标视图的layer上
    [self.view.layer addSublayer:emitterLayer];

CAEmitterCell 粒子

简介:CAEmitterCell类表示CAEmitterLayer对象发出的一个粒子源。 CAEmitterCell定义发射粒子的方向和性质。CAEmitterLayer发射器可以有一系列子粒子,这些子粒子可以让粒子自己发射粒子,也就是CAEmitterCell也可以发射CAEmitterCell

/**
  具体属性清单:
  // 常用属性清单(以空行来划分使用点):
     NSString *name; 			// 粒子名字, 默认为nil

     float birthRate; 			// 粒子的产生率,默认0
     float lifetime; 			// 粒子的生命周期,以秒为单位。默认0
     float lifetimeRange; 		// 粒子的生命周期的范围,以秒为单位。默认0
     
     CGFloat emissionLatitude;// 指定纬度,纬度角代表了在x-z轴平面坐标系中与x轴之间的夹角,默认0:
     CGFloat emissionLongitude; // 指定经度,经度角代表了在x-y轴平面坐标系中与x轴之间的夹角,默认0:
     CGFloat emissionRange; 	//发射角度范围,默认0,以锥形分布开的发射角度。角度用弧度制。粒子均匀分布在这个锥形范围内;
     
     CGFloat velocity; 			// 速度和速度范围,两者默认0
     CGFloat velocityRange;
     CGFloat xAcceleration; 	// x,y,z方向上的加速度分量,三者默认都是0
     CGFloat yAcceleration;
     CGFloat zAcceleration;
     
     CGFloat scale; 			// 缩放比例, 默认是1
     CGFloat scaleRange; 		// 缩放比例范围,默认是0
     CGFloat scaleSpeed; 		// 在生命周期内的缩放速度,默认是0
     
     CGFloat spin; 				// 粒子的平均旋转速度,默认是0
     CGFloat spinRange; 		// 自旋转角度范围,弧度制,默认是0
     
     CGColorRef color; 			// 粒子的颜色,默认白色
     float redRange; 			// 粒子颜色red,green,blue,alpha能改变的范围,默认0
     float greenRange;
     float blueRange;
     float alphaRange;
     float redSpeed; 			// 粒子颜色red,green,blue,alpha在生命周期内的改变速度,默认都是0
     float greenSpeed;
     float blueSpeed;
     float alphaSpeed;
     
     id contents; 				// 粒子的内容,为CGImageRef的对象

     NSArray<CAEmitterCell *> *emitterCells; // 粒子里面的粒子
     
  // 非常不常用属性:
     BOOL enabled;
     NSDictionary *style;
     CGRect contentsRect;
     CGFloat contentsScale;
     NSString *minificationFilter;
     NSString *magnificationFilter;
     float minificationFilterBias;
     
     */

CAEmitterCell的使用方式如下:

 // 1. 配置cell
    CAEmitterCell * showCell = [CAEmitterCell emitterCell];
    
 // 2. 设置属性
    showCell.contents = (id)[[UIImage imageNamed:@"xxx"] CGImage];  // 粒子的内容 是CGImageRef类型的
    
    // 粒子的产生率
    showCell.birthRate = 25.f;
    // 粒子的生命周期,以秒为单位。
    showCell.lifetime = 100.f;
    // 粒子的生命周期的范围,以秒为单位。默认0
    showCell.lifetimeRange = 25.f;
    // 速度,制约粒子生命周期
    // 官方解释为:指定时间如何从父时间空间映射到接收者的时间空间。「必需的」
    // 值越大粒子消失的越快
    showCell.speed = 2.f;
    
    // 速度
    showCell.velocity = 20.f;
    // 速度范围
    showCell.velocityRange = 80.f;
    // 三轴加速度(一般使用Y值)
    showCell.yAcceleration = 90.f;
    //    showCell.xAcceleration = 20.f;
    //    showCell.zAcceleration = 10.f;
    
    // 缩放比列
    showCell.scale = 0.3;
    // 缩放范围
    showCell.scaleRange = 0.5;
    // 在粒子的生命周期内尺度变化的速度。可以做成动画。
    showCell.scaleSpeed = 0.02;
    
    // 设置经纬度(方向)(⭐️⭐️需要在 kCAEmitterLayerPoint 的情况下搭配使用)
    //    showCell.emissionLongitude = M_PI; // 上(-M_PI_2) 下(M_PI_2) 左(M_PI) 右(M_PI_4) 通常使用这个
    //    // showCell.emissionLatitude = -M_PI_2; // 前(-M_PI_2) 后(M_PI_2) 左(M_PI) 右(M_PI_4)
    //    // 设置角度,控制发射范围(受到经纬度的影响)
    //    showCell.emissionRange = M_PI / 6; // 围绕X轴向左90度
    
    // 设置自转速度
    showCell.spin = 0.f;
    // 设置自转方向
    showCell.spinRange = M_PI;
    
    // 设置颜色(⭐️⭐️直接影响到图片的原有颜色)
    //    snowCell.color = [[UIColor colorWithRed:0.5 green:0.f blue:0.5 alpha:1.f] CGColor];
    // 粒子在三个色相中以及可见度的变化程度
    showCell.redRange = 10.f;
    showCell.greenRange = 20.f;
    showCell.blueRange = 30.f;
    
    showCell.redSpeed = 1.f;
    showCell.greenSpeed = 1.f;
    showCell.blueSpeed = 1.f;
    
    showCell.alphaRange = 0.8;
    showCell.alphaSpeed = -0.1f;
    
 // 3.粒子添加到CAEmitterLayer上
    emitterLayer.emitterCells = @[showCell];

看着代码很烦人是吧?把我们上面的 emitterLayer 和 showCell 结合在一起,就是一个完整的粒子发射过程了,给大家看看效果:
iOS开发-iOS粒子发射器开发-iOS粒子动画下雨下雪天气动画开发-CAEmitterLayer粒子发射器-CAEmitterCell粒子开发实践
其实实现的效果非常简单,但一定要自己去尝试上面????代码中,那些注释了的东西。

下雨效果

接下来继续,下雨效果,大家来想想下雨效果是什么样子呢?粒子应该从什么位置发射?应该怎么配置?
思考结束,我们继续:

    // 创建粒子发射器图层
    CAEmitterLayer * rainEmitterLayer = [CAEmitterLayer layer];
    // 设置属性
    // 发射源的形状 是枚举类型  ⭐️因为是下雨 所以要作为 直线发射
    rainEmitterLayer.emitterShape = kCAEmitterLayerLine;
    // 发射模式 从表面发射
    rainEmitterLayer.emitterMode = kCAEmitterLayerSurface;
    // 发射源的size 据定了发射源的大小 设定发射器大小为整个屏幕的大小
    rainEmitterLayer.emitterSize = self.view.frame.size;
    // 发射源的位置 ⭐️因为是下雨 所以要从屏幕上方往下发射(如果想让粒子占据整个屏幕的宽度,设定位置宽度为视图的一半)
    rainEmitterLayer.emitterPosition = CGPointMake(self.view.frame.size.width*0.5, -20);
    // 渲染模式,暂不使用 ⭐️很不常用
    
    // 添加到目标视图的layer上
    [self.view.layer addSublayer:rainEmitterLayer];
    
    // 配置粒子Cell
    CAEmitterCell * rainCell = [CAEmitterCell emitterCell];
    // 设置粒子图片
    rainCell.contents = (id)[[UIImage imageNamed:@"rain"]CGImage];
    
    // 可以以分组的形式来记忆粒子的设定如下:
    // 组1 ⭐️三个参数缺一不可
    // 设置粒子产生率 每秒 60个 ⭐️粒子产生率可以通过 EmitterLayer 来控制
    rainCell.birthRate = 60.f;
    // 设置粒子生命周期 生命周期 40秒
    rainCell.lifetime = 40.f;
    // 设置粒子持续时间,持续时间制约粒子生命周期
    rainCell.speed = 5.f;
    
    // 组2
    // 设置粒子速度
    rainCell.velocity = 20.f;
    // 设置粒子速度范围
    rainCell.velocityRange = 100.f;
    // 设置粒子下落加速度 Y轴
    rainCell.yAcceleration = 2000.f;
    
    // 组3 雨图片需要缩放统一大小 不能使用范围
    // 设置缩放比例
    rainCell.scale = 0.05f;
//    // 设置缩放范围
//    rainCell.scaleRange = 0.8f;
//    // 设置粒子存在期间缩放变化的速度
//    rainCell.scaleSpeed = 0.5f;
    
//    // 组4 雨点不需要旋转
//    // 设置粒子旋转速度
//    rainCell.spin = 0.5f;
//    // 设置粒子旋转范围
//    rainCell.spinRange = M_PI_2;
    
    // 设置粒子颜色 会附和图片修改图片颜色
    rainCell.color = [[UIColor whiteColor]CGColor];
    
    // 添加到粒子发射器
    rainEmitterLayer.emitterCells = @[rainCell];

运行效果如下:
iOS开发-iOS粒子发射器开发-iOS粒子动画下雨下雪天气动画开发-CAEmitterLayer粒子发射器-CAEmitterCell粒子开发实践
我们可以稍加改进,比如绵绵细雨,试想一下,怎么才能做到往一个方向倾斜的呢?我们正常的加速度是:yAcceleration,用来设置粒子下落加速度(Y轴),如果想要倾斜,我们就加上xAcceleration,也就是X轴加速度。运行效果如下:
iOS开发-iOS粒子发射器开发-iOS粒子动画下雨下雪天气动画开发-CAEmitterLayer粒子发射器-CAEmitterCell粒子开发实践
这时候新的问题来了,我们会发现,下雨覆盖不满屏幕了这是为什么呢?之前说了 EmitterLayer 设置属性有:

①发射源的size 据定了发射源的大小 EmitterLayer.emitterSize 目前我们的size是屏幕宽度,即使我们把雨弄倾斜了,发射源的大小和下落位置的大小还是屏幕宽度,这时候我们就需要调整 EmitterLayer 的父 layer 的 View 的大小了,宽度变成 2 倍。

②发射源的位置 EmitterLayer.emitterPosition,之前我们学习到了如果想让粒子占据整个屏幕的宽度,设定位置宽度为视图的一半,这时候也同样。

通过以上两个步骤,倾斜的雨点就会沾满整个屏幕了


下雪效果

好了,我们继续来学习下雪效果,之前下雨效果已经完成了,下雪就很简单啦,直接上代码:

    // 设置发射器图层
    CAEmitterLayer * snowEmitterlayer = [CAEmitterLayer layer];
    // 发射源的形状 是枚举类型 ,因为是下雨 所以要作为 直线发射
    snowEmitterlayer.emitterShape = kCAEmitterLayerLine;
    // 发射模式
    snowEmitterlayer.emitterMode = kCAEmitterLayerSurface;
    // 发射源的size 据定了发射源的大小
    snowEmitterlayer.emitterSize = self.view.frame.size;
    // 发射源的位置 从屏幕上方往下发射
    snowEmitterlayer.emitterPosition = CGPointMake(self.view.frame.size.width*0.5, -10);
    // 渲染模式,暂不使用
    
    [seslf.view.layer addSublayer:snowEmitterlayer];
    
    // 创建粒子
    CAEmitterCell * snowCell = [CAEmitterCell emitterCell];
    // 设置粒子图片
    snowCell.contents = (id)[[UIImage imageNamed:@"[email protected]"]CGImage];
    
    // 组1
    // 设置粒子产生率
    snowCell.birthRate = 10.f;
    // 设置粒子生命周期
    snowCell.lifetime = 40.f;
    // 设置粒子持续时间,持续时间制约粒子生命周期
    snowCell.speed = 5.f;
    
    // 组2
    // 设置粒子速度
    snowCell.velocity = 20.f;
    // 设置粒子速度范围
    snowCell.velocityRange = 100.f;
    // 设置粒子下落加速度 Y轴
    snowCell.yAcceleration = 80.f;
    
    // 组3 雪花图片 需要缩放大小 使用缩放范围
    // 设置缩放比例
    snowCell.scale = 0.2f;
    // 设置缩放范围
    //    snowCell.scaleRange = 0.5f;
    //    // 设置粒子存在期间缩放变化的速度
    //    snowCell.scaleSpeed = 0.5f;
    
    // 组4 雨点不需要旋转
    // 设置粒子旋转速度
    //    snowCell.spin = 0.5f;
    //    // 设置粒子旋转范围
    //    snowCell.spinRange = M_PI_2;
    
    // 设置粒子颜色 会附和图片修改图片颜色
//    snowCell.color = [[UIColor redColor]CGColor];
    
    // 添加到粒子发射器
    snowEmitterlayer.emitterCells = @[snowCell];

运行效果如图:
iOS开发-iOS粒子发射器开发-iOS粒子动画下雨下雪天气动画开发-CAEmitterLayer粒子发射器-CAEmitterCell粒子开发实践
开出来很单调是吧?我们来使用几个属性,让下雪变得好看吧:

①设置粒子缩放范围 snowCell.scaleRange

②设置粒子存在期间缩放变化的速度 snowCell.scaleSpeed

③设置粒子旋转速度 snowCell.spin

④设置粒子旋转范围snowCell.spinRange

如果想设置大雪我们就增加Y轴加速度,图片展示了以上两个修改,运行效果如图:
iOS开发-iOS粒子发射器开发-iOS粒子动画下雨下雪天气动画开发-CAEmitterLayer粒子发射器-CAEmitterCell粒子开发实践


烟火效果

在上文的学习中,我们看到了CAEmitterCell的特性,即:CAEmitterCell也可以发射CAEmitterCell,现在就来给大家具体展示一下:

    // 配置layer
    CAEmitterLayer * fireworksLayer = [CAEmitterLayer layer];
    [self.view.layer addSublayer:fireworksLayer];
    
    // 发射源大小 
    fireworksLayer.emitterSize = CGSizeMake(self.view.layer.bounds.size.width * 0.1, 0.f);
    // 发射位置 在底部向上发射
    fireworksLayer.emitterPosition = CGPointMake(self.view.layer.bounds.size.width * 0.5, self.view.layer.bounds.size.height);
    // 以直线发射
    fireworksLayer.emitterShape = kCAEmitterLayerLine;
    // 在指定位置的表面发射
    fireworksLayer.emitterMode = kCAEmitterLayerSurface;
    // 渲染效果,叠加高亮
    fireworksLayer.renderMode = kCAEmitterLayerAdditive;
    
    // 发射粒子效果
    CAEmitterCell * shootCell = [CAEmitterCell emitterCell];
    shootCell.name = @"shootCell";
    // 粒子产生率 1秒一个
    shootCell.birthRate = 2.f;
    // 粒子存在时间 1.02 上一个销毁了下一个再发出来
    shootCell.lifetime = 1.02f;
    
    // 粒子速度和速度范围 默认是发射模式方向的加速度⭐️
    shootCell.velocity = 600.f;
    shootCell.velocityRange = 100.f;
    // Y方向的加速度 模拟重力影响 发射会感受收到向下的阻碍
    shootCell.yAcceleration = 150.f;
    
    // 发射角度范围 看着更像是到处在放烟火????
    shootCell.emissionRange = M_PI * 0.25;
    
    shootCell.scale = 0.05;
    shootCell.color = [[UIColor redColor] CGColor];
    shootCell.greenRange = 1.f;
    shootCell.redRange = 1.f;
    shootCell.blueRange = 1.f;
    shootCell.contents = (id)[[UIImage imageNamed:@"shoot_white"] CGImage];
    // 烟火在发射的过程中自转
    shootCell.spinRange = M_PI;  // 自转360度
 
    // 爆炸粒子效果
    CAEmitterCell * explodeCell = [CAEmitterCell emitterCell];
    explodeCell.name = @"explodeCell";
    explodeCell.birthRate = 1.f;
    explodeCell.lifetime = 0.5f;
    explodeCell.velocity = 0.f;
    explodeCell.scale = 2.5;
    explodeCell.redSpeed = -1.5;  //爆炸的时候变化颜色
    explodeCell.blueRange = 1.5; //爆炸的时候变化颜色
    explodeCell.greenRange = 1.f; //爆炸的时候变化颜色
    
    // 火花粒子效果
    CAEmitterCell * sparkCell = [CAEmitterCell emitterCell];
    sparkCell.name = @"sparkCell";
    sparkCell.birthRate = 400.f;
    sparkCell.lifetime = 1.5f;
    sparkCell.velocity = 125.f;
    sparkCell.yAcceleration = 75.f;  // 模拟重力影响
    sparkCell.emissionRange = M_PI * 2;  // 360度
    sparkCell.scale = 1.2f;
    sparkCell.contents = (id)[[UIImage imageNamed:@"star_white_stroke"] CGImage];
    sparkCell.redSpeed = 0.4;
    sparkCell.greenSpeed = -0.1;
    sparkCell.blueSpeed = -0.1;
    sparkCell.alphaSpeed = -0.25;
    sparkCell.spin = M_PI * 2;
    
    // 添加动画 每个粒子效果 都可以添加后续动画
    fireworksLayer.emitterCells = @[shootCell];
    // ⭐️粒子添加粒子,再添加粒子,就自动完成了烟火效果
    shootCell.emitterCells = @[explodeCell];
    explodeCell.emitterCells = @[sparkCell];

运行效果如下:
iOS开发-iOS粒子发射器开发-iOS粒子动画下雨下雪天气动画开发-CAEmitterLayer粒子发射器-CAEmitterCell粒子开发实践


需要注意的属性叠加

看到上面有【发射源形状】【发射模式】两个枚举类型,在这里要和大家说一声,这两个枚举类型在使用的时候不好区分而且效果太模糊,给大家看一下运行图,一共有四种发射模式和六种发射源形状,大家可以看一下:
iOS开发-iOS粒子发射器开发-iOS粒子动画下雨下雪天气动画开发-CAEmitterLayer粒子发射器-CAEmitterCell粒子开发实践

iOS开发-iOS粒子发射器开发-iOS粒子动画下雨下雪天气动画开发-CAEmitterLayer粒子发射器-CAEmitterCell粒子开发实践

iOS开发-iOS粒子发射器开发-iOS粒子动画下雨下雪天气动画开发-CAEmitterLayer粒子发射器-CAEmitterCell粒子开发实践

iOS开发-iOS粒子发射器开发-iOS粒子动画下雨下雪天气动画开发-CAEmitterLayer粒子发射器-CAEmitterCell粒子开发实践


总结

想要做好各种粒子发射动画,最关键的几个点如下:

layer需要注意的:
// 发射源的形状 是枚举类型
emitterLayer.emitterShape = kCAEmitterLayerLine;
// 发射模式 枚举类型
emitterLayer.emitterMode = kCAEmitterLayerSurface;

cell需要注意的:
// 设置经纬度(方向)(⭐️⭐️需要在 kCAEmitterLayerPoint 的情况下搭配使用)
showCell.emissionLongitude 上(-M_PI_2) 下(M_PI_2) 左(M_PI) 右(M_PI_4) 通常使用这个
showCell.emissionLatitude 前(-M_PI_2) 后(M_PI_2) 左(M_PI) 右(M_PI_4)
// 设置角度,控制发射范围(受到经纬度的影响)
showCell.emissionRange // 围绕X轴向左【指定度数覆盖范围】发射

链接: https://pan.baidu.com/s/1RpD7pOki6Y3eaBREyOfeBA 提取码: 9ehx