简介: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类表示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 *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 结合在一起,就是一个完整的粒子发射过程了,给大家看看效果:
其实实现的效果非常简单,但一定要自己去尝试上面?代码中,那些注释了的东西。
接下来继续,下雨效果,大家来想想下雨效果是什么样子呢?粒子应该从什么位置发射?应该怎么配置?
思考结束,我们继续:
// 创建粒子发射器图层
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];
运行效果如下:
我们可以稍加改进,比如绵绵细雨,试想一下,怎么才能做到往一个方向倾斜的呢?我们正常的加速度是:yAcceleration,用来设置粒子下落加速度(Y轴),如果想要倾斜,我们就加上xAcceleration,也就是X轴加速度。运行效果如下:
这时候新的问题来了,我们会发现,下雨覆盖不满屏幕了这是为什么呢?之前说了 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:@"snow@3x"]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];
运行效果如图:
开出来很单调是吧?我们来使用几个属性,让下雪变得好看吧:
①设置粒子缩放范围 snowCell.scaleRange
②设置粒子存在期间缩放变化的速度 snowCell.scaleSpeed
③设置粒子旋转速度 snowCell.spin
④设置粒子旋转范围snowCell.spinRange
如果想设置大雪我们就增加Y轴加速度,图片展示了以上两个修改,运行效果如图:
在上文的学习中,我们看到了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];
运行效果如下:
看到上面有【发射源形状】【发射模式】两个枚举类型,在这里要和大家说一声,这两个枚举类型在使用的时候不好区分而且效果太模糊,给大家看一下运行图,一共有四种发射模式和六种发射源形状,大家可以看一下:
想要做好各种粒子发射动画,最关键的几个点如下:
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