一、CAEmitterLayer&CAEmitterCells
在 UIKit 中,粒子系统由两部分组成:
1、一个或多个 CAEmitterCells :发射器电池可以看作是单个粒子的原型(例如,一个单一的粉扑在一团烟雾)。当散发出一个粒子,UIKit根据这个发射粒子和定义的基础上创建一个随机粒子。此原型包括一些属性来控制粒子的图片,颜色,方向,运动,缩放比例和生命周期。
2、一个或多个 CAEmitterLayers, 但通常只有一个:这个发射的层主要控制粒子的形状(例如,一个点,矩形或圆形)和发射的位置(例如,在矩形内,或边缘)。这个层具有全局的乘法器,可以施加到系统内的CAEmitterCells。这些给你一个简单的方法覆盖的所有粒子的变化。比如一个人为的例子将改变x雨来模拟风的速度。
二、属性
1、CAEmitterLayer属性
(1)、装着CAEmitterCell对象的数组,被用于把粒子投放到layer上;
@property(nullable, copy) NSArray<CAEmitterCell *> *emitterCells;
(2)、粒子产生系数,默认1.0;
@property float birthRate;
(3)、粒子生命周期;
@property float lifetime;
(4)、发射源发射位置;
@property CGPoint emitterPosition;
(5)、发射源z坐标位置;
@property CGFloat emitterZPosition;
(6)、发射源大小;
@property CGSize emitterSize;
(7)、决定粒子形状的深度联系:emitter shape;
@property CGFloat emitterDepth;
(8)、发射源的形状;
@property(copy) NSString *emitterShape;
/** `emitterShape' values. **/
CA_EXTERN NSString * const kCAEmitterLayerPoint
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerLine
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerRectangle
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerCuboid
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerCircle
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerSphere
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
(9)、发射模式;
@property(copy) NSString *emitterMode;
/** `emitterMode' values. **/
CA_EXTERN NSString * const kCAEmitterLayerPoints
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerOutline
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerSurface
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerVolume
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
(10)、渲染模式;
@property(copy) NSString *renderMode;
/** `renderMode' values. **/
CA_EXTERN NSString * const kCAEmitterLayerUnordered
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerOldestFirst
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerOldestLast
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerBackToFront
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerAdditive
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
(11)、粒子速度;
@property float velocity;
(12)、粒子的缩放比例;
@property float scale;
(13)、自旋转速度;
@property float spin;
(14)、用于初始化随机数产生的种子;
@property unsigned int seed;
(15)、是否启动三维效果
@property BOOL preservesDepth;
2、CAEmitterCell属性
(1)、粒子的名字;
@property(nullable, copy) NSString *name;
(2)、粒子是否被渲染;
@property(getter=isEnabled) BOOL enabled;
(3)、粒子参数的速度乘数因子;每秒发射的粒子数量;
@property float birthRate;
(4)、粒子的生命周期;
@property float lifetime;
(5)、生命周期范围差;
lifetime= lifetime(+/-) lifetimeRange
@property float lifetimeRange;
(6)、发射的z轴方向的角度;
@property CGFloat emissionLatitude;
(7)、x-y平面的发射方向;
@property CGFloat emissionLongitude;
(8)、周围发射角度;
@property CGFloat emissionRange;
(9)、粒子的速度;
@property CGFloat velocity;
(10)、粒子的速度范围差;
@property CGFloat velocityRange;
(11)、粒子x/y/z方向的加速度分量
@property CGFloat xAcceleration;
@property CGFloat yAcceleration;
@property CGFloat zAcceleration;
(12)、缩放比例;
@property CGFloat scale;
(13)、缩放比例范围差;
@property CGFloat scaleRange;
(14)、缩放比例速度;
@property CGFloat scaleSpeed;
(15)、粒子旋转角度;
@property CGFloat spin;
(16)、粒子旋转角度范围差;
@property CGFloat spinRange;
(17)、粒子的颜色
@property(nullable) CGColorRef color;
(18)、一个粒子的颜色red/green/blue/alpha能改变的范围;
@property float redRange;
@property float greenRange;
@property float blueRange;
@property float alphaRange;
(19)、粒子red/green/blue/alpha在生命周期内的改变速度;
@property float redSpeed;
@property float greenSpeed;
@property float blueSpeed;
@property float alphaSpeed;
(20)、是个CGImageRef的对象,既粒子要展现的图片;
@property(nullable, strong) id contents;
(21)、应该画在contents里的子rectangle;
@property CGRect contentsRect;
(22)、减小自己的大小
@property(copy) NSString *minificationFilter;
三、直播粒子动画
1、CAEmitterLayer实现
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) CAEmitterLayer *emitterLayer;
@property (nonatomic ,weak)UIView *backView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIView *backView = [[UIView alloc]initWithFrame:CGRectMake((CGRectGetWidth(self.view.frame) - 100)/2, 0, 100, CGRectGetHeight(self.view.frame))];
backView.layer.masksToBounds = YES;
[self.view addSubview:backView];
self.backView = backView;
[self.backView.layer addSublayer:self.emitterLayer];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSLog(@"1111");
}
- (CAEmitterLayer *)emitterLayer{
if (!_emitterLayer) {
_emitterLayer = [CAEmitterLayer layer];
//发射器在xy平面的中心位置
_emitterLayer.emitterPosition = CGPointMake(CGRectGetWidth(self.backView.frame)/2, CGRectGetHeight(self.backView.frame) - 50);
//发射器的尺寸大小
_emitterLayer.emitterSize = CGSizeMake(20, 20);
//渲染模式
_emitterLayer.renderMode = kCAEmitterLayerOldestFirst;
NSMutableArray *array = [NSMutableArray array];
// 创建粒子
for (int i = 1; i < 5; i++) {
// 发射单元
CAEmitterCell *stepCell = [CAEmitterCell emitterCell];
// 粒子的创建速率,默认为1/s
stepCell.birthRate = 1;
// 粒子存活时间
stepCell.lifetime = arc4random_uniform(4) + 4;
// 粒子的生存时间容差
stepCell.lifetimeRange = 1.5;
UIImage *image =
[UIImage imageNamed:[NSString stringWithFormat:@"good%d", i]];
// 粒子显示的内容
stepCell.contents = (id)[image CGImage];
// 粒子的运动速度
stepCell.velocity = arc4random_uniform(100) + 100;
// 粒子速度的容差
stepCell.velocityRange = 80;
// 粒子在xy平面的发射角度
stepCell.emissionLongitude = M_PI + M_PI_2;
// 粒子发射角度的容差
stepCell.emissionRange = M_PI_2 / 6;
// 缩放比例
stepCell.scale = 0.3;
stepCell.scaleSpeed = 0.3;
[array addObject:stepCell];
}
_emitterLayer.emitterCells = array;
_emitterLayer.backgroundColor = [UIColor yellowColor].CGColor;
}
return _emitterLayer;
}
2、UIView实现
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self animateInView:self.view];
}
- (void)animateInView:(UIView *)view{
//添加心图片
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 400, 30, 30)];
int nameI = arc4random()%4 + 1;
imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"good%d", nameI]];
[view addSubview:imageView];
//初始化状态
imageView.transform = CGAffineTransformMakeScale(0, 0);
imageView.alpha = 0;
//在底部 由无到有 又小变大的弹性动画
[UIView animateWithDuration:0.5
delay:0.0
usingSpringWithDamping:0.6
initialSpringVelocity:0.8
options:UIViewAnimationOptionCurveEaseOut
animations:^{
imageView.transform = CGAffineTransformIdentity;
imageView.alpha = 0.9;
}
completion:NULL];
//放大后向左或向右旋转一定角度动画
NSInteger i = arc4random_uniform(2);
NSInteger rotationDirection = 1 - (2*i);
NSInteger rotationFraction = arc4random_uniform(10);
NSTimeInterval totalAnimationDuration = 3;
[UIView animateWithDuration:totalAnimationDuration
animations:^{
imageView.transform = CGAffineTransformMakeRotation(rotationDirection*PI/(16 + rotationFraction*0.2));
}];
//S型动画
CGFloat heartSize = CGRectGetWidth(imageView.bounds);
CGFloat heartCenterX = imageView.center.x;
CGFloat viewHeight = CGRectGetHeight(view.bounds);
UIBezierPath *heartTravelPath = [UIBezierPath bezierPath];
[heartTravelPath moveToPoint:imageView.center];
//随机结束点
CGPoint endPoint = CGPointMake(heartCenterX + (rotationDirection)*arc4random_uniform(2*heartSize),viewHeight/6.0 + arc4random_uniform(viewHeight/4.0));
NSInteger j = arc4random_uniform(2);
NSInteger travelDirection = 1 - (2 * j); // -1 OR 1
//绘制S型曲线 随机点
CGFloat xDelta = (heartSize/2.0 + arc4random_uniform(2 * heartSize))*travelDirection;
CGFloat yDelta =
MAX(endPoint.y, MAX(arc4random_uniform(8 * heartSize), heartSize));
//控制点1 控制点2
CGPoint controlPoint1 = CGPointMake(heartCenterX + xDelta, yDelta);
CGPoint controlPoint2 = CGPointMake(heartCenterX - xDelta, yDelta);
[heartTravelPath addCurveToPoint:endPoint
controlPoint1:controlPoint1
controlPoint2:controlPoint2];
CAKeyframeAnimation *keyFrameAnimation =
[CAKeyframeAnimation animationWithKeyPath:@"position"];
keyFrameAnimation.path = heartTravelPath.CGPath;
keyFrameAnimation.timingFunction =
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
keyFrameAnimation.duration = totalAnimationDuration + endPoint.y / viewHeight;
[imageView.layer addAnimation:keyFrameAnimation forKey:@"positionOnPath"];
// 动画消失
[UIView animateWithDuration:totalAnimationDuration
animations:^{
imageView.alpha = 0.0;
}
completion:^(BOOL finished) {
[imageView removeFromSuperview];
}];
}