iosiOS技术分享UI相关 动画 动态cell UIcollectionview

iOS - Core Animation 死亡笔记:初窥

2016-11-08  本文已影响1486人  Candy7
你若盛开,蝴蝶自来(图片来自网络)

简介:
Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍。也就是说,使用少量的代码就可以实现非常强大的功能。
关于Core Animation完整的详细资料,这里有一份详细的介绍:http://blog.csdn.net/mad2man/article/details/16928891(由海水的味道翻译)

一、隐式动画

1.图层是Core Animation的核心,那么什么是CALayer

2.什么是隐式动画

#import "ViewController.h"

@interface ViewController ()
@property (nonatomic,strong) CALayer *layer; 
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 手动创建layer
    self.layer = [CALayer layer];
    self.layer.frame = CGRectMake(0, 0, 200, 200);
    self.layer.backgroundColor = [UIColor blackColor].CGColor;
    [self.view.layer addSublayer:self.layer];
}
// 点击的时候更改layer的位置.(用于测试是否会产生隐式动画)
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    self.layer.frame = CGRectMake(100, 100, 200, 200);
}
@end

那么如何关闭隐式动画呢?
CALayer隐式动画实际上是自动执行了CATransaction,CATransaction默认动画时间0.25s

// 点击的时候更改layer的位置.(用于测试是否会产生隐式动画)
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [CATransaction begin];
    [CATransaction setDisableActions:YES];
        self.layer.frame = CGRectMake(100, 100, 200, 200);
    [CATransaction commit];
}

效果图:

左:未关闭隐式动画<br>右:关闭隐式动画

将隐式动画时间改成2s,并改变layer的背景颜色

    [CATransaction begin];
    // 改变动画时间:设置为2s
    [CATransaction setAnimationDuration:2.0f];
    [CATransaction setDisableActions:NO];
    self.layer.frame = CGRectMake(100, 100, 200, 200);
    self.layer.backgroundColor = [UIColor yellowColor].CGColor;
    [CATransaction commit];

基于UIView的block的动画允许你在动画结束的时候提供一个完成的动作。CATranscation接口提供的+ setCompletionBlock:方法也有同样的功能

    [CATransaction setCompletionBlock:^{
        NSLog(@"完成了");
    }];
    [CATransaction commit];
    NSLog(@"将要完成");

二、显式动画

  • 隐式动画是在iOS平台创建动态用户界面的一种直接方式,也是UIKit动画机制的基础,不过它并不能涵盖所有的动画类型。

属性动画 - CAPropertyAnimation

属性动画作用于图层的某个单一属性,并指定了它的一个目标值,或者一连串将要做动画的值。属性动画分为两种:基础和关键帧。


  动画其实就是一段时间内发生的改变,最简单的形式就是从一个值改变到另一个值.
  CABasicAnimation 继承 CAPropertyAnimation, 而CAPropertyAnimation是c所有动画类型的一个抽象基类
  CAPropertyAnimation 通过指定动画的 KeyPath 作用于一个单一的属性.

  类型的转换
id obj = @(float) // CGFloat 类型转换
id obj = [NSValue valueWithCGPoint:point] // CGPoint
id obj = [NSValue valueWithCGsize:point] // CGsize
id obj = [NSValue valueWithCGPoint:point] // CGPoint
id obj = [NSValue valueWithCGRect:point] // CGRect


CABasicAnimation 继承 CAPropertyAnimation,添加了如下属性

```

id fromValue; // 动画开始前属性值
id toValue; // 动画结束后属性值
id byValue; // 动画过程中改变的值

  • 这里的 id 类型 可以作用于不同的属性,比如:'数字','矢量','颜色','图片';
- 用于CAPropertyAnimation的一些类型转换
![](https://img.haomeiwen.com/i2055866/eeed8a89cf16b02e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


写代码啦~~~    ^ & ^


                        '通过CABasicAnimation来设置图层背景色'

import "ViewController.h"

@interface ViewController ()
@property (nonatomic,strong) CALayer *layer;
@end

@implementation ViewController


![](https://img.haomeiwen.com/i2055866/e21c5bdf1a4e66ae.gif?imageMogr2/auto-orient/strip)

> 有小伙伴提出怎么在动画结束后保持效果,在这里感谢:**"霸气侧漏"**的这位蜀黍提供的代码;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;


- CAAnimationDelegate
> 我们可以看到有两个方法.那么,优化上面的代码
![](https://img.haomeiwen.com/i2055866/b6c1e3a8ce808680.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

- 关键帧动画 - CAKeyframeAnimation

> CAKeyframeAnimation是另一种UIKit没有暴露出来但功能强大的类。和CABasicAnimation类似,CAKeyframeAnimation同样是CAPropertyAnimation的一个子类,它依然作用于单一的一个属性,但是和CABasicAnimation不一样的是,它不限制于设置一个起始和结束的值,而是可以根据一连串随意的值来做动画。

使用CAKeyframeAnimation 做颜色变化

@interface ViewController ()
@property (nonatomic,strong) CALayer *layer;
@end

@implementation ViewController

`CAKeyframeAnimation`不能自动把当前值作为第一帧(类似1于1CABasicAnimation把`fromValue`设为`nil`),所以为了动画的平滑特性,我们需要开始和结束的关键帧来匹配当前属性的值
![CAKeyframeAnimation](https://img.haomeiwen.com/i2055866/1a94e6427d0acf9a.gif?imageMogr2/auto-orient/strip)

CAKeyframeAnimation有另一种方式去指定动画,就是使用CGPath.可以结合UIBezierpath创建路径,进行做动画
`Tips:关于UIBezierPath,可以参考我上一篇`:[iOS-UIBezierPath和各种layer把我玩坏了](http://www.jianshu.com/p/9ac372683735)

- 根据UIBezierPath进行Animation

@interface ViewController ()
@property (nonatomic,strong) UIView *bezierPathView;
@property (nonatomic,strong) UIBezierPath *path;
@end

@implementation ViewController

warning 如果不适用自动对齐,效果不会太逼真.可以自己尝试效果

animation.rotationMode = kCAAnimationRotateAuto;
[self.bezierPathView.layer addAnimation:animation forKey:nil];

}


这样一个路径图就构造出来了,^_^

![CAKeyframeAnimation构造路径图](https://img.haomeiwen.com/i2055866/707ccdae16fa6577.gif?imageMogr2/auto-orient/strip)

- 虚拟属性

> 
- 属性动画实际上是针对关键路径而不是一个键,这就意味着可以对子属性甚至是虚拟属性进行做动画.
-  什么是虚拟属性? 
  如果想要对一个物体做旋转动画,应该用到transform属性,因为CALayer没有显示提供角度或者方向之类的属性

利用transform对layer做动画

import "ViewController.h"

@interface ViewController ()

@property (nonatomic,strong) UIView *animationView;
@property (nonatomic,strong) CALayer *layer;

@end

@implementation ViewController

}


![rotation](https://img.haomeiwen.com/i2055866/e9b4e038fa03b9e5.gif?imageMogr2/auto-orient/strip)

**这里如果我们把M_PI(180°)调整到M_PI*2(360°),就会发现怎么都不会动了.因为:toValue的结果是360°,又回到了最初的状态,所以值根本没有变,没有动画效果,那么如何改变呢?**

- *改变 :  对 `transform.rotaion` 进行动画 *



> 为什么用`transform.rotation`?
1. 我们可以不通过关键帧一次旋转多余180°的动画
- 可以用相对值 (byValue)
- 可以用不用CATransform3D
- 不会和transform.positon以及transform.scale冲突,完全分开进行独立的动画

![transform.rotation](https://img.haomeiwen.com/i2055866/ff7bd3e15be40d0c.gif?imageMogr2/auto-orient/strip)

- 组动画 - CAAnimationGroup

> CAAnimationGroup可以把上面所述的动画类型进行组合在一起.
 - CAAnimationGroup 也是继承于CAAnimtion的子类
 - CAAnimationGroup 添加了 `animaitons` 属性

组合 `CAKeyframeAnimtion` 和 ` CABasicAnimation`

import "ViewController.h"

@interface ViewController ()

@property (nonatomic,strong) UIView *animationView;
@property (nonatomic,strong) CALayer *layer;
@property (nonatomic,strong) CAAnimationGroup *group;
@end

@implementation ViewController

self.layer = [CALayer layer];
self.layer.frame = CGRectMake(0, 0, 80, 80);
self.layer.position =CGPointMake(100, 150);
self.layer.cornerRadius = 40;
self.layer.masksToBounds = YES;
self.layer.backgroundColor = (__bridge CGColorRef _Nullable)((__bridge id)[UIColor whiteColor].CGColor);
;
[self.view.layer addSublayer:self.layer];

CALayer *imgLayer = [CALayer layer];
imgLayer.frame = CGRectMake(0, 0, 50, 50);
imgLayer.position = CGPointMake(40, 40);
imgLayer.contents = (__bridge id)[UIImage imageNamed:@"1.jpg"].CGImage;
[self.layer addSublayer:imgLayer];

// position
CAKeyframeAnimation *keyAnimation = [CAKeyframeAnimation animation];
keyAnimation.keyPath = @"position";
keyAnimation.path = path.CGPath;
keyAnimation.rotationMode = kCAAnimationRotateAuto;

// transform.rotation
CABasicAnimation *basicAnimaiton = [CABasicAnimation animation];
basicAnimaiton.keyPath = @"transform.rotation";
basicAnimaiton.byValue = @(M_PI * 2);

// opacity
CAKeyframeAnimation *alphaAnimation = [CAKeyframeAnimation animation];
alphaAnimation.keyPath = @"opacity";
alphaAnimation.values = @[@0.3,@0.5,@0.8,@0.1,@.4,@.9,@0.1,@.5,@.2,@.7,@.3,@1.0];

// backgroupColors
CAKeyframeAnimation *colorAnimtion = [CAKeyframeAnimation alloc];
colorAnimtion.keyPath = @"backgroundColor";
colorAnimtion.values = @[(__bridge id)[UIColor whiteColor].CGColor,
                         (__bridge id)[UIColor redColor].CGColor,
                         (__bridge id)[UIColor orangeColor].CGColor,
                         (__bridge id)[UIColor yellowColor].CGColor,
                         (__bridge id)[UIColor greenColor].CGColor,
                         (__bridge id)[UIColor cyanColor].CGColor,
                         (__bridge id)[UIColor blueColor].CGColor,
                         (__bridge id)[UIColor purpleColor].CGColor,
                         (__bridge id)[UIColor whiteColor].CGColor];

//groupAnimation
CAAnimationGroup *groupAnimation = [CAAnimationGroup animation];
groupAnimation.animations = @[keyAnimation,alphaAnimation,colorAnimtion,basicAnimaiton];
groupAnimation.duration = 5.0;

self.group = groupAnimation;

}


![CAAnimtionGroup](https://img.haomeiwen.com/i2055866/f162a46bfc1282fb.gif?imageMogr2/auto-orient/strip)

- 过渡动画 - CATransition

> - `CATransition` 同样继承于 `CAAnimation` 
![](https://img.haomeiwen.com/i2055866/0744d96ed7419bcd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 
- CATransition 在 API中已经有很清楚的说明了.他有一个`type`,`subtype`来标记变换效果
![](https://img.haomeiwen.com/i2055866/3f2669d4a8322491.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

简单的imageView加载图片

@interface ViewController ()

@property (nonatomic,strong) UIImageView *imageView;
@property (nonatomic,strong) NSArray *imageArr;

@end

@implementation ViewController

}

![imageView加载图片](https://img.haomeiwen.com/i2055866/0632b6c2429779dc.gif?imageMogr2/auto-orient/strip)

>- 隐式过渡
当设置了CALayer的`content`属性的时候,`CATransition`是默认的行为。但对于UIView关联的图层,或者是其他隐式动画,这个特性依然是被禁用的,但是对于自己创建的`Layer`,`layer.contents`图片都会自动附上`Fade`的动画。

- 使用UIKit提供的动画方法做过渡动画

![UIKit](https://img.haomeiwen.com/i2055866/866fabbc90d4e9c7.gif?imageMogr2/auto-orient/strip)   


 Tips: 最初的梦想,紧握在手上,让我们在最美的时光里,做最好的自己!


![](https://img.haomeiwen.com/i2055866/72ed5a88ddbf47a7.jpg?imageMogr2/auto-orient/strip)
上一篇下一篇

猜你喜欢

热点阅读