一、UIView基础动画
通过修改对应视图(UIView)的属性,可以实现一些最基础的动画效果.
- 位置和尺寸的修改:
bounds frame center transform
- 外观样式的变化:
backgroundColor alpha
示例1:改变UIView的frame
[UIView animateWithDuration:1.0 animations:^{
self.imageView.left += 150;
}];
与之对应的还有:
[UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse animations:^{
self.imageView.left += 200;
} completion:^(BOOL finished) { //动画执行完成操作
}];
示例2、反复来回移动效果
[UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse animations:^{
self.imageView.left += 150;
} completion:^(BOOL finished) {
}];
示例3、弹簧效果,可用于弹出框动画效果
//参数说明:usingSpringWithDamping 弹性阻尼系数取值0~1,值越大,弹框幅度越小
//initialSpringVelocity:初始速度
[UIView animateWithDuration:1 delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:0.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.testButton.top -= 160;
} completion:nil];
示例4 3D效果的转场动画
[UIView transitionWithView:self.imageView duration:1.0 options:UIViewAnimationOptionTransitionCurlUp animations:^{
self.imageView.image = [UIImage imageNamed:@"6"];
} completion:nil];
同理还有下面方法从一个view过渡到另一个view:
[UIView transitionFromView:self.imageView toView:self.imageView2 duration:1.0 options:UIViewAnimationOptionTransitionFlipFromRight completion:^(BOOL finished) {
}];
示例5、动画组
在实际应用中,不可避免的需要将几个动画按照次序进行先后执行.
[UIView animateKeyframesWithDuration: 4 delay: 0 options: UIViewKeyframeAnimationOptionCalculationModeLinear animations: ^{
__block CGPoint center = self.imageView.center;
[UIView addKeyframeWithRelativeStartTime: 0 relativeDuration: 0.1 animations: ^{
self.imageView.center = (CGPoint){ center.x + 15, center.y + 80 };
}];
[UIView addKeyframeWithRelativeStartTime: 0.1 relativeDuration: 0.15 animations: ^{
self.imageView.center = (CGPoint){ center.x + 45, center.y + 185 };
}];
[UIView addKeyframeWithRelativeStartTime: 0.25 relativeDuration: 0.3 animations: ^{
self.imageView.center = (CGPoint){ center.x + 90, center.y + 295 };
}];
[UIView addKeyframeWithRelativeStartTime: 0.55 relativeDuration: 0.3 animations: ^{
self.imageView.center = (CGPoint){ center.x + 180, center.y + 375 };
}];
[UIView addKeyframeWithRelativeStartTime: 0.85 relativeDuration: 0.15 animations: ^{
self.imageView.center = (CGPoint){ center.x + 270, center.y + 435 };
}];
[UIView addKeyframeWithRelativeStartTime: 0 relativeDuration: 1 animations: ^{
self.imageView.transform = CGAffineTransformMakeRotation(M_PI);
}];
} completion: nil];
以上5个示例中用到的参数
options
说明:
1、常规动画属性设置(可以同时选择多个进行设置):
UIViewAnimationOptionLayoutSubviews:动画过程中保证子视图跟随运动。
UIViewAnimationOptionAllowUserInteraction:动画过程中允许用户交互。
UIViewAnimationOptionBeginFromCurrentState:所有视图从当前状态开始运行。
UIViewAnimationOptionRepeat:重复运行动画。
UIViewAnimationOptionAutoreverse :动画运行到结束点后仍然以动画方式回到初始点。
UIViewAnimationOptionOverrideInheritedDuration:忽略嵌套动画时间设置。
UIViewAnimationOptionOverrideInheritedCurve:忽略嵌套动画速度设置。
UIViewAnimationOptionAllowAnimatedContent:动画过程中重绘视图(注意仅仅适用于转场动画)。
UIViewAnimationOptionShowHideTransitionViews:视图切换时直接隐藏旧视图、显示新视图,而不是将旧视图从父视图移除(仅仅适用于转场动画)
UIViewAnimationOptionOverrideInheritedOptions :不继承父动画设置或动画类型。
2、 动画速度控制(可从其中选择一个设置)
UIViewAnimationOptionCurveEaseInOut:动画先缓慢,然后逐渐加速。
UIViewAnimationOptionCurveEaseIn :动画逐渐变慢。
UIViewAnimationOptionCurveEaseOut:动画逐渐加速。
UIViewAnimationOptionCurveLinear :动画匀速执行,默认值。
3、转场类型(仅适用于转场动画设置,可以从中选择一个进行设置,基本动画、关键帧动画不需要设置)
UIViewAnimationOptionTransitionNone:没有转场动画效果。
UIViewAnimationOptionTransitionFlipFromLeft :从左侧翻转效果。
UIViewAnimationOptionTransitionFlipFromRight:从右侧翻转效果。
UIViewAnimationOptionTransitionCurlUp:向后翻页的动画过渡效果。
UIViewAnimationOptionTransitionCurlDown :向前翻页的动画过渡效果。
UIViewAnimationOptionTransitionCrossDissolve:旧视图溶解消失显示下一个新视图的效果。
UIViewAnimationOptionTransitionFlipFromTop :从上方翻转效果。
UIViewAnimationOptionTransitionFlipFromBottom:从底部翻转效果。
二、layer动画
View Animations可以实现一些简单的动效,但并不能够完全满足开发使用,自定义程度比较低,为此我们来学习下Layer Animations.
那么Layer有哪些可以自定义动画的属性呢?
- 位置和尺寸: bounds position transform
- 边框: borderColor borderWidth cornerRadius
- 阴影: shadowOffset shadowOpacity shadowPath shadowRadius
- 内容: contents mask opacity
等等,以上仅仅只是一部分.
示例一:CABasicAnimation实现简单动画
CABasicAnimation *ani = [CABasicAnimation animationWithKeyPath:@"position.x"];
ani.fromValue = @(100);
//结束位置
ani.toValue = @(300);
//持续时间
ani.duration = 1.0;
//延迟0.3秒执行
ani.beginTime = CACurrentMediaTime() + 0.3;
[self.imageView.layer addAnimation:ani forKey:nil];
我们会看到动画执行完成会立刻回到初始状态,如果保持在结束状态添加下面代码即可:
// 保证fillMode起作用
ani.removedOnCompletion = NO;
// 动画结束后,layer会保持结束状态
ani.fillMode = kCAFillModeForwards;
fillMode
的几个值的分别代表的含义:
kCAFillModeRemoved : 默认样式 动画结束后会回到layer的开始的状态
kCAFillModeForwards : 动画结束后,layer会保持结束状态
kCAFillModeBackwards : layer跳到fromValue的值处,然后从fromValue到toValue播放动画,最后回到layer的开始的状态
kCAFillModeBoth : kCAFillModeForwards和kCAFillModeBackwards的结合,即动画结束后layer保持在结束状态
我们可以通过代理获取动画执行开始、结束时刻,秩序遵守CAAnimationDelegate
即可
实现代码如下:
// 设置名称 因为delegate方法中可能有多个CABasicAnimation设置了代理,根据name获取不同CABasicAnimation对象
[ani setValue:@"form" forKey:@"name"];
// 方便代理中可以拿到layer CABasicAnimation对象可以作用于多个UIView,上一步获取CABasicAnimation对象,这一步获取作用于哪个View上
[ani setValue:self.imageView.layer forKey:@"layer"];
//设置代理可以知道动画开始、结束时间
ani.delegate = self;
两个代理方法,在动画结束后做一个特效缩放操作
//CAAnimationDelegate
- (void)animationDidStart:(CAAnimation *)anim{
NSLog(@"动画开始了");
}
//CAAnimationDelegate
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
NSString *animName = [anim valueForKey:@"name"];
if (animName) {
if ([animName isEqualToString:@"form"]) {//找到CABasicAnimation对象
CALayer *layer = [anim valueForKey:@"layer"];//找到view的layer
[anim setValue:nil forKeyPath:@"layer"];
CABasicAnimation *pulse = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
pulse.fromValue = @(1.25);
pulse.toValue = @(1.0);
pulse.duration = 3.25;
[layer addAnimation:pulse forKey:nil];
}
}
}
在设计交互中,常常会碰到这样的一个问题,在动画的执行过程中,由于用户的点击操作,需要提前终止动画,该怎么实现呢?很简单
// forKey以前基本是设置为nil的,现在派上用场了.因为self.imageView上可能添加了很多动画,forKey就是为了区别哪一个
self.imageView.layer.addAnimation(flyRight, forKey: "position")
// 添加到需要终止的地方,就可以随时终止动画了
self.imageView.layer.removeAnimationForKey("position")
// 移除dogImageView上所有动画
self.imageView.layer.removeAllAnimations()
示例二 CAAnimationGroup动画组
类似View Animations中的动画组,只不过这个动画组中的动画是同时执行的
CAAnimationGroup *aniGroup = [[CAAnimationGroup alloc]init];
// 延迟1秒
aniGroup.beginTime = CACurrentMediaTime() + 1;
//整个动画时间
aniGroup.duration = 1.0;
aniGroup.removedOnCompletion = NO;
aniGroup.fillMode = kCAFillModeBoth;
// 缓慢加速缓慢减
aniGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
//重复次数
aniGroup.repeatCount = 2;
// 来回往返执行 设置是否原路返回默认为不
aniGroup.autoreverses = YES;
//速度
aniGroup.speed = 2.0;
CABasicAnimation *scaleAni = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scaleAni.fromValue = @(1.0);
scaleAni.toValue = @(1.5);
CABasicAnimation *rotateAni = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
rotateAni.fromValue = @(0.0);
rotateAni.toValue = @(M_PI_4);
CABasicAnimation *fadeAni = [CABasicAnimation animationWithKeyPath:@"opacity"];
fadeAni.fromValue = @(1.0);
fadeAni.toValue = @(0.5);
aniGroup.animations = @[scaleAni, rotateAni, fadeAni];
[self.imageView.layer addAnimation:aniGroup forKey:nil];
示例三 CASpringAnimation弹簧效果
类似View Animations中的弹簧动画,代码实现:
CASpringAnimation *scaleDown = [CASpringAnimation animationWithKeyPath:@"transform.scale"];
scaleDown.fromValue = @(1.0);
scaleDown.toValue = @(1.5);
// settlingDuration:结算时间(根据动画参数估算弹簧开始运动到停止的时间,动画设置的时间最好根据此时间来设置)
scaleDown.duration = scaleDown.settlingDuration;
// mass:质量(影响弹簧的惯性,质量越大,弹簧惯性越大,运动的幅度越大) 默认值为1
scaleDown.mass = 4.0;
// stiffness:弹性系数(弹性系数越大,弹簧的运动越快)默认值为100
scaleDown.stiffness = 1500.0;
// damping:阻尼系数(阻尼系数越大,弹簧的停止越快)默认值为10
scaleDown.damping = 50;
// initialVelocity:初始速率(弹簧动画的初始速度大小,弹簧运动的初始方向与初始速率的正负一致,若初始速率为0,表示忽略该属性)默认值为0
scaleDown.initialVelocity = 100;
[self.imageView.layer addAnimation:scaleDown forKey:nil];
-
CASpringAnimation
的重要属性: -
mass
:质量(影响弹簧的惯性,质量越大,弹簧惯性越大,运动的幅度越大) -
stiffness
:弹性系数(弹性系数越大,弹簧的运动越快) -
damping
:阻尼系数(阻尼系数越大,弹簧的停止越快) -
initialVelocity
:初始速率(弹簧动画的初始速度大小,弹簧运动的初始方向与初始速率的正负一致,若初始速率为0,表示忽略该属性) -
settlingDuration
:结算时间(根据动画参数估算弹簧开始运动到停止的时间,动画设置的时间最好根据此时间来设置)
示例四 CATransition专场动画
CATransition *transition = [[CATransition alloc]init];
transition.type = @"rippleEffect";
transition.subtype = kCATransitionFromRight;
transition.duration = 1.0;
//切换图片
[UIView transitionWithView:self.imageView duration:1.0 options:UIViewAnimationOptionTransitionFlipFromRight animations:^{
self.imageView.image = [UIImage imageNamed:@"2"];
} completion:nil];
[self.imageView.layer addAnimation:transition forKey:nil];
转场动画过渡效果:
另外对于支持方向设置的动画类型还包含子类型:
kCATransitionFromRight 从右侧转场
kCATransitionFromLeft 从左侧转场
kCATransitionFromTop 从顶部转场
kCATransitionFromBottom 从底部转场
示例五 CAKeyframeAnimation
开发中情况多种多样,从一个值到另一个值的fromValue
和toValue
属性并不能高效的满足开发需要,比如我们要将一个view一次经过三个点呢?难道分为两次去做,那太麻烦了,CAKeyframeAnimation
有个属性values
是个数组完美替代了fromValue
,toValue
,我们可以把三个点放进values
数组,解决问题
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
anim.duration = 2.0;
anim.repeatCount = MAXFLOAT;
anim.values = @[
[NSValue valueWithCGPoint:CGPointMake(100, 100)],
[NSValue valueWithCGPoint:CGPointMake(200, 300)],
[NSValue valueWithCGPoint:CGPointMake(50, 30)],
[NSValue valueWithCGPoint:CGPointMake(300, 100)]
];
anim.keyTimes = @[@(0.0), @(0.33), @(0.66), @(1.0)];
[self.imageView.layer addAnimation:anim forKey:nil];
效果二:
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];
anim.duration = 2.0;
anim.repeatCount = MAXFLOAT;
anim.values = @[@(0.0), @(-M_PI_4/4), @(0.0), @(M_PI_4/4), @(0.0)];
anim.keyTimes = @[@(0.0), @(0.25), @(0.5), @(0.75), @(1.0)];
[self.imageView.layer addAnimation:anim forKey:nil];
动画中
animationWithKeyPath:??
取值如下:
transform.scale = 比例轉換
transform.scale.x = 闊的比例轉換
transform.scale.y = 高的比例轉換
transform.rotation.z = 平面圖的旋轉
translation: 平移,值是NSSize或CGSize translation.x, translation.y, translation.z
opacity = 透明度
margin
zPosition
backgroundColor 背景颜色
cornerRadius 圆角
borderWidth
bounds
contents
contentsRect
cornerRadius
frame
hidden
mask
masksToBounds
opacity
position
shadowColor
shadowOffset
shadowOpacity
shadowRadius
三 CAShapeLayer动画
在这我们就不讲CALayer
与UIBezierPath
使用,大家可以自己百度学习,很简单
示例一
//贝塞尔曲线
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(100, 400)];
// [path addQuadCurveToPoint:CGPointMake(300, 400) controlPoint:CGPointMake(150, 300)];
[path addCurveToPoint:CGPointMake(300, 400) controlPoint1:CGPointMake(150, 300) controlPoint2:CGPointMake(200, 450)];
//创建CAShapeLayer对象
CAShapeLayer *layer = [CAShapeLayer layer];
layer.path = path.CGPath;
layer.strokeColor = [UIColor purpleColor].CGColor;
layer.fillColor = [UIColor clearColor].CGColor;
[self.view.layer addSublayer:layer];
//添加动画
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animation.fromValue = @(0);
animation.toValue = @(1);
animation.duration = 2.0;
[layer addAnimation:animation forKey:nil];
动画效果:
效果二:
layer.strokeStart = 0.5;
layer.strokeEnd = 0.5;
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
animation.fromValue = @(0.5);
animation.toValue = @(0);
animation.duration = 2;
CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animation2.fromValue = @(0.5);
animation2.toValue = @(1);
animation2.duration = 2;
//逐渐加粗
CABasicAnimation *animation3 = [CABasicAnimation animationWithKeyPath:@"lineWidth"];
animation3.fromValue = @(1);
animation3.toValue = @(10);
animation3.duration = 2;
[layer addAnimation:animation forKey:nil];
[layer addAnimation:animation2 forKey:nil];
[layer addAnimation:animation3 forKey:nil];
动画效果:
实例二
说明:实例二、三不是动画效果,仅仅是对CAShapeLayer使用,可简单看下
实现下面效果
很明显它可以用 CAShapeLayer + UIBezierPath 来做,思路大概是这样,先移动到左上方的位置,然后向下划线,然后往右划线,然后往上划线,还剩一个盖子,这个盖子就用一个控制点控制曲率,非常简单,代码如下
CGSize finalSize = CGSizeMake(self.view.width, 200);
CGFloat layerHeight = finalSize.height * 0.3;
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(0, layerHeight)];
[path addLineToPoint:CGPointMake(0, finalSize.height)];
[path addLineToPoint:CGPointMake(finalSize.width, finalSize.height)];
[path addLineToPoint:CGPointMake(finalSize.width, layerHeight)];
[path addQuadCurveToPoint:CGPointMake(0, layerHeight) controlPoint:CGPointMake(finalSize.width/2, 0)];
CAShapeLayer *layer = [CAShapeLayer layer];
layer.position = CGPointMake(0, (self.view.height - 200)/2);
layer.path = path.CGPath;
layer.fillColor = [UIColor orangeColor].CGColor;
[self.view.layer addSublayer:layer];
实现效果:
示例三
代码实现
#import "TestView.h"
@implementation TestView
- (void)setMaskLayer{
CGFloat viewWidth = CGRectGetWidth(self.frame);
CGFloat viewHeight = CGRectGetHeight(self.frame);
CGFloat rightSpace = 10.;
CGFloat topSpace = 15.;
CGPoint point1 = CGPointMake(0, 0);
CGPoint point2 = CGPointMake(viewWidth-rightSpace, 0);
CGPoint point3 = CGPointMake(viewWidth-rightSpace, topSpace);
CGPoint point4 = CGPointMake(viewWidth, topSpace);
CGPoint point5 = CGPointMake(viewWidth-rightSpace, topSpace+10.);
CGPoint point6 = CGPointMake(viewWidth-rightSpace, viewHeight);
CGPoint point7 = CGPointMake(0, viewHeight);
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:point1];
[path addLineToPoint:point2];
[path addLineToPoint:point3];
[path addLineToPoint:point4];
[path addLineToPoint:point5];
[path addLineToPoint:point6];
[path addLineToPoint:point7];
[path closePath];
CAShapeLayer *layer = [CAShapeLayer layer];
layer.path = path.CGPath;
self.layer.mask = layer;
}
@end
//使用
TestView *testView = [[TestView alloc]initWithFrame:CGRectMake(100, 100, 150, 200)];
testView.backgroundColor = [UIColor cyanColor];
[testView setMaskLayer];
[self.view addSubview:testView];
四 CAReplicatorLayer动画
CAReplicatorLayer
是一个容器层-你添加内容到其中让复制图层复制其中内容。如果你把一个单一的形状-在复制层将显示在屏幕上几种形状。
很酷的是你可以预先设定复制多少几何图形并且设定副本之间的距离,透明度或颜色都可以发生变化。因此您可以创建很酷的动画效果。
示例一
//创建图层
CAReplicatorLayer *replicator = [CAReplicatorLayer layer];
replicator.position = self.view.center;
replicator.bounds = CGRectMake(0, 0, 250, 250);
replicator.backgroundColor = [UIColor lightGrayColor].CGColor;
[self.view.layer addSublayer:replicator];
//创建一个振动层
CALayer *vibrateLayer = [CALayer layer];
CGFloat width = 25;
CGFloat height = 100;
vibrateLayer.bounds = CGRectMake(0, 0, width, height);
vibrateLayer.anchorPoint = CGPointMake(0.5, 1);
vibrateLayer.position = CGPointMake(width * 0.5, replicator.bounds.size.height);
vibrateLayer.cornerRadius = 10;
vibrateLayer.backgroundColor = [UIColor magentaColor].CGColor;
[replicator addSublayer:vibrateLayer];
//创建帧动画
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale.y"];
anim.duration = 0.5;
anim.values = @[@(1),@(0.5),@(0)];
//旋转后再旋转到原来的位置,反极性开始
anim.autoreverses = YES;
anim.repeatCount = MAXFLOAT;
[vibrateLayer addAnimation:anim forKey:nil];
//设置复制层需要复制的个数
replicator.instanceCount = 4;
//设置复制出来子层的位移
replicator.instanceTransform = CATransform3DMakeTranslation(50, 0, 0);
// 执行动画的延迟
replicator.instanceDelay = 0.2;
//改变颜色
replicator.instanceAlphaOffset = - 0.1;
replicator.instanceRedOffset = -0.2;
效果:
其中用到的属性说明:
//拷贝的次数
@property NSInteger instanceCount;
//是否开启景深效果
@property BOOL preservesDepth;
//当CAReplicatorLayer的子Layer层进行动画的时候,拷贝的副本执行动画的延时
@property CFTimeInterval instanceDelay;
//拷贝副本的3D变换
@property CATransform3D instanceTransform;
//拷贝副本的颜色变换
@property(nullable) CGColorRef instanceColor;
//每个拷贝副本的颜色偏移参数
@property float instanceRedOffset;
@property float instanceGreenOffset;
@property float instanceBlueOffset;
//每个拷贝副本的透明度偏移参数
@property float instanceAlphaOffset;
实例二 加载动画
int height = 40;
int width = 40;
CAReplicatorLayer *replicatorLayerMAIN = [CAReplicatorLayer layer];
replicatorLayerMAIN.bounds = self.view.bounds;
replicatorLayerMAIN.position = CGPointMake(self.view.frame.size.width/2.0, self.view.frame.size.height/2.0);
[self.view.layer addSublayer:replicatorLayerMAIN];
replicatorLayerMAIN.masksToBounds = YES;
replicatorLayerMAIN.instanceCount = 15;
replicatorLayerMAIN.instanceDelay = 1/15.0;
CGFloat angle = (2.0 * M_PI) / (15.0);
replicatorLayerMAIN.instanceTransform = CATransform3DMakeRotation(angle, 0, 0, 1);
CALayer *replicatorLayer = [CALayer layer];
replicatorLayer.bounds = CGRectMake(0, 0, width, height);
replicatorLayer.backgroundColor = [UIColor whiteColor].CGColor;
replicatorLayer.cornerRadius = width/2.0;
replicatorLayer.position = CGPointMake(self.view.frame.size.width/2.0, self.view.frame.size.height/2.0 - 100);
[replicatorLayerMAIN addSublayer:replicatorLayer];
CABasicAnimation *moveRectangle = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
moveRectangle.fromValue = @1;
moveRectangle.toValue = @0.1;
//否则刚开始出现的所有点一样大,所以时间减1
moveRectangle.beginTime = CACurrentMediaTime() - 1;
moveRectangle.duration = 1;
moveRectangle.repeatCount = HUGE;
[replicatorLayer addAnimation:moveRectangle forKey:@"ss"];
运行效果
五 CAEmitterLayer动画
CAEmitterLayer
是ios5中苹果引入了一个新的CALayer
子类。CAEmitterLayer
是一个高性能的粒子引擎,可以用来做一些绚丽的粒子系统,比如爆炸,雪花火焰等等。
在UIKit中,粒子系统由两部分组成:
- 一个或多个
CAEmitterCells
:发射器电池可以看作是单个粒子的原型(例如,一个单一的粉扑在一团烟雾)。当散发出一个粒子,UIKit根据这个发射粒子和定义的基础上创建一个随机粒子。此原型包括一些属性来控制粒子的图片,颜色,方向,运动,缩放比例和生命周期。 - 一个或多个
CAEmitterLayers
,但通常只有一个:这个发射的层主要控制粒子的形状(例如,一个点,矩形或圆形)和发射的位置(例如,在矩形内,或边缘)。这个层具有全局的乘法器,可以施加到系统内的CAEmitterCells
。这些给你一个简单的方法覆盖的所有粒子的变化。比如一个人为的例子将改变x雨来模拟风的速度。
CAEmitterLayer
提供了一个基于Core Animation
的粒子发射系统,粒子用CAEmitterCell
来初始化。粒子画在背景层盒边界上,CAEmitterLayers
其属性说明:
birthRate:粒子产生系数,默认1.0;
emitterCells: 装着CAEmitterCell对象的数组,被用于把粒子投放到layer上;
emitterDepth:决定粒子形状的深度联系:emitter shape
emitterMode:发射模式
NSString * const kCAEmitterLayerPoints;
NSString * const kCAEmitterLayerOutline;
NSString * const kCAEmitterLayerSurface;
NSString * const kCAEmitterLayerVolume;
emitterPosition:发射位置
emitterShape:发射源的形状:
NSString * const kCAEmitterLayerPoint;
NSString * const kCAEmitterLayerLine;
NSString * const kCAEmitterLayerRectangle;
NSString * const kCAEmitterLayerCuboid;
NSString * const kCAEmitterLayerCircle;
NSString * const kCAEmitterLayerSphere;
emitterSize:发射源的尺寸大;
emitterZposition:发射源的z坐标位置;
lifetime:粒子生命周期
preservesDepth:不是多很清楚(粒子是平展在层上)
renderMode:渲染模式:
NSString * const kCAEmitterLayerUnordered;
NSString * const kCAEmitterLayerOldestFirst;
NSString * const kCAEmitterLayerOldestLast;
NSString * const kCAEmitterLayerBackToFront;
NSString * const kCAEmitterLayerAdditive;
scale:粒子的缩放比例:
seed:用于初始化随机数产生的种子
spin:自旋转速度
velocity:粒子速度
CAEmitterCell
属性说明:
alphaRange: 一个粒子的颜色alpha能改变的范围;
alphaSpeed:粒子透明度在生命周期内的改变速度;
birthrate:粒子参数的速度乘数因子;
blueRange:一个粒子的颜色blue 能改变的范围
blueSpeed: 粒子blue在生命周期内的改变速度;
color: 粒子的颜色
contents:是个CGImageRef的对象,既粒子要展现的图片;
contentsRect:应该画在contents里的子rectangle:
emissionLatitude:发射的z轴方向的角度
emissionLongitude:x-y平面的发射方向
emissionRange;周围发射角度
emitterCells:粒子发射的粒子
enabled:粒子是否被渲染
greenrange: 一个粒子的颜色green 能改变的范围;
greenSpeed: 粒子green在生命周期内的改变速度;
lifetime:生命周期
lifetimeRange:生命周期范围
magnificationFilter:不是很清楚好像增加自己的大小
minificatonFilter:减小自己的大小
minificationFilterBias:减小大小的因子
name:粒子的名字
redRange:一个粒子的颜色red 能改变的范围;
redSpeed: 粒子red在生命周期内的改变速度;
scale:缩放比例:
scaleRange:缩放比例范围;
scaleSpeed:缩放比例速度:
spin:子旋转角度
spinrange:子旋转角度范围
style:不是很清楚:
velocity:速度
velocityRange:速度范围
xAcceleration:粒子x方向的加速度分量
yAcceleration:粒子y方向的加速度分量
zAcceleration:粒子z方向的加速度分量
示例一 雪花下效果
CAEmitterLayer *snowEmitter = [CAEmitterLayer layer];
//例子发射位置
snowEmitter.emitterPosition = CGPointMake(120,-20);
//发射源的尺寸大小
snowEmitter.emitterSize = CGSizeMake(self.view.bounds.size.width * 20, 20);
//发射模式
snowEmitter.emitterMode = kCAEmitterLayerVolume;
//发射源的形状
snowEmitter.emitterShape = kCAEmitterLayerLine;
snowEmitter.shadowOpacity = 1.0;
snowEmitter.shadowRadius = 0.0;
snowEmitter.shadowOffset = CGSizeMake(0.0, 1.0);
//粒子边缘的颜色
snowEmitter.shadowColor = [[UIColor redColor] CGColor];
[self.view.layer insertSublayer:snowEmitter atIndex:0];
//创建雪花类型的粒子
CAEmitterCell *snowflake = [CAEmitterCell emitterCell];
//粒子的名字
snowflake.name = @"snow";
//粒子参数的速度乘数因子
snowflake.birthRate = 5.0;
snowflake.lifetime = 120.0;
//粒子速度
snowflake.velocity = 10.0;
//粒子的速度范围
snowflake.velocityRange = 10;
//粒子y方向的加速度分量
snowflake.yAcceleration = 2;
//周围发射角度
snowflake.emissionRange = 0.5 * M_PI;
//子旋转角度范围
snowflake.spinRange = 0.25 * M_PI;
snowflake.contents = (id)[[UIImage imageNamed:@"3"] CGImage];
//设置雪花形状的粒子的颜色
snowflake.color = [[UIColor colorWithRed:0.200 green:0.258 blue:0.543 alpha:1.000] CGColor];
//创建星星形状的粒子
CAEmitterCell *snowflake1 = [CAEmitterCell emitterCell];
//粒子的名字
snowflake1.name = @"snow";
//粒子参数的速度乘数因子
snowflake1.birthRate = 5.0;
snowflake1.lifetime = 120.0;
//粒子速度
snowflake1.velocity =10.0;
//粒子的速度范围
snowflake1.velocityRange = 10;
//粒子y方向的加速度分量
snowflake1.yAcceleration = 2;
//周围发射角度
snowflake1.emissionRange = 0.5 * M_PI;
//子旋转角度范围
snowflake1.spinRange = 0.25 * M_PI;
//粒子的内容和内容的颜色
snowflake1.contents = (id)[[UIImage imageNamed:@"4"] CGImage];
snowflake1.color = [[UIColor colorWithRed:0.600 green:0.658 blue:0.743 alpha:1.000] CGColor];
snowEmitter.emitterCells = [NSArray arrayWithObjects:snowflake,snowflake1,nil];
实例二 爆炸效果
// 雪花//////////////////////////////////////////
// Configure the particle emitter to the top edge of the screen
CAEmitterLayer *snowEmitter = [CAEmitterLayer layer];
snowEmitter.emitterPosition = CGPointMake(self.view.bounds.size.width / 2.0, -30); //粒子发射器的位置
snowEmitter.emitterSize = CGSizeMake(self.view.bounds.size.width * 2.0, 0.0);;
snowEmitter.emitterMode = kCAEmitterLayerOutline;
snowEmitter.emitterShape = kCAEmitterLayerRectangle;
snowEmitter.shadowOpacity = 1.0;
snowEmitter.shadowRadius = 0.0;
snowEmitter.shadowOffset = CGSizeMake(0.0, 1.0);
snowEmitter.shadowColor = [[UIColor whiteColor] CGColor];
[self.view.layer addSublayer:snowEmitter];
CAEmitterCell *snowflake = [CAEmitterCell emitterCell];
// 随机颗粒的大小
snowflake.scale = 0.2;
snowflake.scaleRange = 0.5;
// 缩放比列速度
// snowflake.scaleSpeed = 0.1;
// 粒子参数的速度乘数因子;
snowflake.birthRate = 20.0; //每秒产生的 cell数量
//生命周期
snowflake.lifetime = 60.0; //在屏幕上的生存周期
// 粒子速度
snowflake.velocity = 20; // falling down slowly
snowflake.velocityRange = 10;
// 粒子y方向的加速度分量
snowflake.yAcceleration = 2;
// 周围发射角度
snowflake.emissionRange = 0.5 * M_PI;// some variation in angle
// 自动旋转
snowflake.spinRange = 0.25 * M_PI; // slow spin
snowflake.contents = (id) [[UIImage imageNamed:@"3"] CGImage];
snowflake.color = [[UIColor colorWithRed:0.600 green:0.658 blue:0.743 alpha:1.000] CGColor];
snowEmitter.emitterCells = [NSArray arrayWithObject:snowflake];
// [self.view.layer insertSublayer:snowEmitter atIndex:0];
//// 雪花//////////////////////////////////////////
//// 雪花//////////////////////////////////////////
// Cells spawn in the bottom, moving up
CAEmitterLayer *fireworksEmitter = [CAEmitterLayer layer];
CGRect viewBounds = self.view.layer.bounds;
fireworksEmitter.emitterPosition = CGPointMake(viewBounds.size.width/2.0, viewBounds.size.height);
fireworksEmitter.emitterSize = CGSizeMake(viewBounds.size.width/2.0, 0.0);
fireworksEmitter.emitterMode = kCAEmitterLayerOutline;
fireworksEmitter.emitterShape = kCAEmitterLayerLine;
fireworksEmitter.renderMode = kCAEmitterLayerAdditive;
fireworksEmitter.seed = (arc4random()%100)+1;
// Create the rocket
CAEmitterCell* rocket = [CAEmitterCell emitterCell];
rocket.birthRate = 5.0; //每秒产生的 cell数量
rocket.emissionRange = 0.25 * M_PI; // some variation in angle
rocket.velocity = 380;
rocket.velocityRange = 380;
rocket.yAcceleration = 75;
rocket.lifetime = 1.02;// we cannot set the birthrate < 1.0 for the burst //屏幕上的生命周期
rocket.contents = (id) [[UIImage imageNamed:@"4"] CGImage];
// rocket.contents = (id) [[UIImage imageNamed:[NSString stringWithFormat:@"%u",(arc4random()%8)+1]]CGImage];
rocket.scale = 0.3;
// rocket.color = [[UIColor colorWithRed:1 green:0 blue:0 alpha:1] CGColor];
rocket.greenRange = 1.0;// different colors
rocket.redRange = 1.0;
rocket.blueRange = 1.0;
rocket.spinRange = M_PI; // slow spin
// the burst object cannot be seen, but will spawn the sparks
// we change the color here, since the sparks inherit its value
CAEmitterCell* burst = [CAEmitterCell emitterCell];
burst.birthRate = 1.0;// at the end of travel //每秒产生的 cell数量
burst.velocity = 0;
burst.scale = 2.5;
burst.redSpeed =-1.5; // shifting
burst.blueSpeed =+1.5; // shifting
burst.greenSpeed =+1.0; // shifting
burst.lifetime = 0.35; //屏幕上的生命周期
// and finally, the sparks
CAEmitterCell* spark = [CAEmitterCell emitterCell];
spark.birthRate = 400; //每秒产生的 cell数量
spark.velocity = 125;
spark.emissionRange = 2* M_PI; // 360 deg
spark.yAcceleration = 75; // gravity
spark.lifetime = 3; //屏幕上的生命周期
spark.contents = (id) [[UIImage imageNamed:@"5"] CGImage];
//spark.contents = (id) [[UIImage imageNamed:[NSString stringWithFormat:@"%u",(arc4random()%8)+1]]CGImage];
spark.scale =0.4;
spark.scaleSpeed =-0.2;
spark.greenSpeed =-0.1;
spark.redSpeed = 0.6;
spark.blueSpeed =-0.1;
spark.alphaSpeed =-0.5;
spark.spin = 2* M_PI;
spark.spinRange = 2* M_PI;
// putting it together
fireworksEmitter.emitterCells = [NSArray arrayWithObject:rocket];
rocket.emitterCells = [NSArray arrayWithObject:burst];
burst.emitterCells = [NSArray arrayWithObject:spark];
[self.view.layer addSublayer:fireworksEmitter];
效果:
六 参考链接
iOS粒子系统CAEmitterLayer
CAEmitterLayer和CAEmitterCell
放肆的使用UIBezierPath和CAShapeLayer画各种图形