前几篇文章中,我详细的说明了Core Animation相关的理论知识。这一节,我将举例说明基本动画的使用。
一、 CABasicAnimation
首先我创建一个用于实现动画的图层,代码如下:
- - (void)viewDidLoad {
- [super viewDidLoad];
- CALayer *layer = [CALayer layer];
- layer.position = CGPointMake(100, 100);
- layer.bounds = CGRectMake(0, 0, 100, 100);
- layer.backgroundColor = [UIColor redColor].CGColor;
- [self.view.layer addSublayer:layer];
- self.layer = layer;
- }
1. 透明度变化
动画代码如下:
- CABasicAnimation *fadeAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
- // 动画起始值
- fadeAnimation.fromValue = @(1.0);
- // 动画结束值
- fadeAnimation.toValue = @(0.0);
- // 动画持续时间
- fadeAnimation.duration = 2.0;
- // key 动画标识
- [self.layer addAnimation:fadeAnimation forKey:@"opacityAnimation"];
动画效果如下:
可以看出,动画是按照设想的执行,但是在动画结束后,又返回原来的状态了。
原因分析:注意到,本例中,我使用的显式动画,不同于隐式动画,隐式动画会更新图层对象的值。而显式动画不会更改图层树中的数据。显式动画仅是创建了一个动画。在动画结束之后,Core Animation从图层中移除该动画对象并使用当前的数据值重绘图层。(所以显式动画会出现动画结束后,突然回到原始位置的情况)。
解决方案:
I. 更新赋值图层属性
这种方案的原理就是动画开始的时候,就确定图层的最终值;这样操作的话,当动画结束并且被移除后,显示的是图层树中的值。代码如下:
- CABasicAnimation *fadeAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
- // 动画起始值
- fadeAnimation.fromValue = @(1.0);
- // 动画结束值
- fadeAnimation.toValue = @(0.0);
- // 动画持续时间
- fadeAnimation.duration = 3.0;
- /*一开始就确定动画结束后,图层最终的透明值*/
- self.layer.opacity = 0;
- // key 动画标识
- [self.layer addAnimation:fadeAnimation forKey:@"opacityAnimation"];
II. 不移除动画,并填充
- CABasicAnimation *fadeAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
- // 动画起始值
- fadeAnimation.fromValue = @(1.0);
- // 动画结束值
- fadeAnimation.toValue = @(0.0);
- // 动画持续时间
- fadeAnimation.duration = 3.0;
- /* 动画执行完毕后不要删除动画 */
- fadeAnimation.removedOnCompletion = NO;
- /* 保持最新的状态 */
- fadeAnimation.fillMode = kCAFillModeForwards;
- // key 动画标识
- [self.layer addAnimation:fadeAnimation forKey:@"opacityAnimation"];</span>
- - (void)dealloc {
- [self.layer removeAnimationForKey:@"opacityAnimation"];
- }
有人会问,为什么不使用UIView的block操作来实现此功能呢?因为这一节中,我是主要讲解Core Animation相关的图层动画,解释其执行过程及原理;大家在明白这里过程及原理后,适用UIView的block操作(它的内部实现就是借助图层动画,只是进行了一层封装)来实现动画,也是极好的。
2. 平移动画
动画代码如下:
- // 1.创建动画对象
- CABasicAnimation *anim = [CABasicAnimation animation];
- // 2.设置动画对象
- // keyPath决定了执行怎样的动画, 调整哪个属性来执行动画
- anim.keyPath = @"position";
- // anim.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
- // toValue : 最终变成什么值
- // byValue : 增加多少值
- anim.byValue = [NSValue valueWithCGPoint:CGPointMake(200, 200)];
- anim.duration = 2.0;
- /**让图层保持动画执行完毕后的状态**/
- // 动画执行完毕后不要删除动画
- anim.removedOnCompletion = NO;
- // 保持最新的状态(动画结束后的状态)
- anim.fillMode = kCAFillModeForwards;
- // 3.添加动画
- [self.layer addAnimation:anim forKey:nil];
动画效果如下:
3. 缩放动画
动画代码如下:
- // 1.创建动画对象
- CABasicAnimation *anim = [CABasicAnimation animation];
- // 2.设置动画对象
- // keyPath决定了执行怎样的动画, 调整哪个属性来执行动画
- anim.keyPath = @"bounds";
- // anim.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
- anim.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];
- anim.duration = 2.0;
- /**让图层保持动画执行完毕后的状态**/
- // 动画执行完毕后不要删除动画
- anim.removedOnCompletion = NO;
- // 保持最新的状态
- anim.fillMode = kCAFillModeForwards;
- // 3.添加动画
- [self.layer addAnimation:anim forKey:nil];
动画效果如下:
4. 旋转动画
动画代码如下:
- // 1.创建动画对象
- CABasicAnimation *anim = [CABasicAnimation animation];
- // 2.设置动画对象
- // keyPath决定了执行怎样的动画, 调整哪个属性来执行动画
- anim.keyPath = @"transform";
- // anim.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
- anim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI, 1, -1, 0)];
- anim.duration = 2.0;
- anim.removedOnCompletion = NO;
- anim.fillMode = kCAFillModeForwards;
- // 3.添加动画
- [self.layer addAnimation:anim forKey:nil];
动画效果如下:
二、CAKeyframeAnimation
1. 连续动画
动画代码如下:
- //CABasicAnimation fromValue --> toValue
- CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
- anim.keyPath = @"position";
- NSValue *v1 = [NSValue valueWithCGPoint:CGPointZero];
- NSValue *v2 = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
- NSValue *v3 = [NSValue valueWithCGPoint:CGPointMake(100, 200)];
- NSValue *v4 = [NSValue valueWithCGPoint:CGPointMake(250, 250)];
- anim.values = @[v1, v2, v3, v4];
- anim.duration = 2.0;
- anim.removedOnCompletion = NO;
- // 保持最新的状态
- anim.fillMode = kCAFillModeForwards;
- [self.redView.layer addAnimation:anim forKey:nil];
动画效果如下:
2. 缓冲动画
动画代码如下:
- CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
- anim.keyPath = @"position";
- anim.removedOnCompletion = NO;
- anim.fillMode = kCAFillModeForwards;
- anim.duration = 4.0;
- CGMutablePathRef path = CGPathCreateMutable();
- CGPathAddEllipseInRect(path, NULL, CGRectMake(100, 100, 200, 200));
- anim.path = path;
- CGPathRelease(path);
- // 设置动画的执行节奏
- // kCAMediaTimingFunctionEaseInEaseOut : 一开始比较慢, 中间会加速, 临近结束的时候, 会变慢
- anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
- anim.delegate = self;
- [self.redView.layer addAnimation:anim forKey:nil];
动画效果如下:
注意到:代码中也可以对动画设置代理,用来监听动画的执行动作。比如下面代码:
- #pragma mark - 动画的代理方法
- #pragma mark 动画开始的时候调用
- - (void)animationDidStart:(CAAnimation *)anim
- {
- NSLog(@"animationDidStart");
- }
- #pragma mark 动画结束的时候调用
- - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
- {
- NSLog(@"animationDidStop");
- }
3. 抖动效果
动画代码如下:
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- self.myImage.layer.cornerRadius = 15;
- self.myImage.layer.masksToBounds = YES;
- }
- - (IBAction)start {
- CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
- anim.keyPath = @"transform.rotation";
- anim.values = @[@(Angle(-5)),@(Angle(5)),@(Angle(-5))];
- anim.repeatCount = 10;
- anim.duration = 0.3;
- [self.myImage.layer addAnimation:anim forKey:@"Shake"];
- }
- - (IBAction)stop {
- [self.myImage.layer removeAnimationForKey:@"Shake"];
- }
动画效果如下:
三、 CATransition
动画代码如下:
- - (IBAction)prev {
- self.index--;
- if(self.index == -1){
- self.index = 8;
- }
- UIImage *prevImage = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",self.index+1]];
- self.myImage.image = prevImage;
- CATransition *anim = [CATransition animation];
- anim.type = @"pageUnCurl";
- anim.subtype = @"kCATransitionFromLeft";
- [self.myImage.layer addAnimation:anim forKey:nil];
- }
- - (IBAction)next {
- self.index++;
- if(self.index == 9){
- self.index = 0;
- }
- UIImage *nextImage = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",self.index+1]];
- self.myImage.image = nextImage;
- CATransition *anim = [CATransition animation];
- anim.type = @"pageCurl";
- anim.subtype = @"kCATransitionFromRight";
- [self.myImage.layer addAnimation:anim forKey:nil];
- }
动画效果如下:
对代码中得type及subtype 进行说明(大家可以自己尝试看看效果):
type:
pageCurl 向上翻一页
pageUnCurl 向下翻一页
rippleEffect 滴水效果
suckEffect 收缩效果,如一块布被抽走
cube 立方体效果
oglFlip 上下翻转效果
subtype:
kCATransitionFade 交叉淡化过渡
kCATransitionMoveIn 新视图移到旧视图上面
kCATransitionPush 新视图把旧视图推出去
kCATransitionReveal 将旧视图移开,显示下面的新视图
四、 CAAnimationGroup
动画代码如下:
- // 1.创建旋转动画对象
- CABasicAnimation *rotate = [CABasicAnimation animation];
- rotate.keyPath = @"transform.rotation";
- rotate.toValue = @(M_PI);
- // 2.创建缩放动画对象
- CABasicAnimation *scale = [CABasicAnimation animation];
- scale.keyPath = @"transform.scale";
- scale.toValue = @(0.0);
- // 3.平移动画
- CABasicAnimation *move = [CABasicAnimation animation];
- move.keyPath = @"transform.translation";
- move.toValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
- // 4.将所有的动画添加到动画组中
- CAAnimationGroup *group = [CAAnimationGroup animation];
- group.animations = @[rotate, scale, move];
- group.duration = 5.0;
- group.removedOnCompletion = NO;
- group.fillMode = kCAFillModeForwards;
- [self.iconView.layer addAnimation:group forKey:nil];
动画效果如下:
总结:在本章节中,对Core Animation中所涉及的相关动画(平移,缩放,旋转,组合)进行了举例说明。在后面的几个章节中,我将逐步介绍动画的高级应用及应用案例。 To Be Continued...
转载自:http://blog.csdn.net/sinat_27706697/article/details/46864775