动画缓冲

CATransaction的动画缓冲

考虑一个场景,一辆车行驶在一定距离内,它并不会一开始就以60mph的速度行驶,然后到达终点后突然变成0mph。一是因为需要无限大的加速度(即使是最好的车也不会在0秒内从0跑到60),另外不然的话会干死所有乘客。在现实中,它会慢慢地加速到全速,然后当它接近终点的时候,它会慢慢地减速,直到最后停下来。

Core Animation使用缓冲来使动画移动更平滑更自然,

一种方法是使用物理引擎来对运动物体的摩擦和动量来建模,然而这会使得计算过于复杂。我们称这种类型的方程为缓冲函数,幸运的是,Core Animation内嵌了一系列标准函数提供给我们使用。

CAMediaTimingFunction

那么该如何使用缓冲方程式呢?首先需要设置CAAnimation的timingFunction属性,是CAMediaTimingFunction类的一个对象。如果想改变隐式动画的计时函数,同样也可以使用CATransaction的+setAnimationTimingFunction:方法。

这里有一些方式来创建CAMediaTimingFunction,最简单的方式是调用+timingFunctionWithName:的构造方法。这里传入如下几个常量之一:

kCAMediaTimingFunctionLinear     //1
kCAMediaTimingFunctionEaseIn     //2
kCAMediaTimingFunctionEaseOut    //3
kCAMediaTimingFunctionEaseInEaseOut  //4
kCAMediaTimingFunctionDefault    //5

//1
kCAMediaTimingFunctionLinear选项创建了一个线性的计时函数,同样也是CAAnimation的timingFunction属性为空时候的默认函数。线性步调对于那些立即加速并且保持匀速到达终点的场景会有意义(例如射出枪膛的子弹),但是默认来说它看起来很奇怪,因为对大多数的动画来说确实很少用到。

//2
kCAMediaTimingFunctionEaseIn常量创建了一个慢慢加速然后突然停止的方法。对于之前提到的自由落体的例子来说很适合,或者比如对准一个目标的导弹的发射。

//3
kCAMediaTimingFunctionEaseOut则恰恰相反,它以一个全速开始,然后慢慢减速停止。它有一个削弱的效果,应用的场景比如一扇门慢慢地关上,而不是砰地一声。

//4
kCAMediaTimingFunctionEaseInEaseOut创建了一个慢慢加速然后再慢慢减速的过程。这是现实世界大多数物体移动的方式,也是大多数动画来说最好的选择。如果只可以用一种缓冲函数的话,那就必须是它了。那么你会疑惑为什么这不是默认的选择,实际上当使用UIView的动画方法时,他的确是默认的,但当创建CAAnimation的时候,就需要手动设置它了。

//5
最后还有一个kCAMediaTimingFunctionDefault,它和kCAMediaTimingFunctionEaseInEaseOut很类似,但是加速和减速的过程都稍微有些慢。它和kCAMediaTimingFunctionEaseInEaseOut的区别很难察觉,可能是苹果觉得它对于隐式动画来说更适合(然后对UIKit就改变了想法,而是使用kCAMediaTimingFunctionEaseInEaseOut作为默认效果),虽然它的名字说是默认的,但还是要记住当创建显式的CAAnimation它并不是默认选项(换句话说,默认的图层行为动画用kCAMediaTimingFunctionDefault作为它们的计时方法)。

Demo

@interface ViewController ()
@property (nonatomic, strong) CALayer *colorLayer;
@end
@implementation ViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    //create a red layer
    self.colorLayer = [CALayer layer];
    self.colorLayer.frame = CGRectMake(0, 0, 100, 100);
    self.colorLayer.position = CGPointMake(self.view.bounds.size.width/2.0, self.view.bounds.size.height/2.0);
    self.colorLayer.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:self.colorLayer];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //configure the transaction
    [CATransaction begin];
    [CATransaction setAnimationDuration:1.0];
    [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
    //set the position
    self.colorLayer.position = [[touches anyObject] locationInView:self.view];
    //commit transaction
    [CATransaction commit];
}
@end

UIView的动画缓冲

UIKit的动画也同样支持这些缓冲方法的使用,尽管语法和常量有些不同,为了改变UIView动画的缓冲选项,给options参数添加如下常量之一:

UIViewAnimationOptionCurveEaseInOut 
UIViewAnimationOptionCurveEaseIn 
UIViewAnimationOptionCurveEaseOut 
UIViewAnimationOptionCurveLinear

它们和CAMediaTimingFunction紧密关联,UIViewAnimationOptionCurveEaseInOut是默认值(这里没有kCAMediaTimingFunctionDefault相对应的值了)。

 [UIView animateWithDuration:1.0 delay:0.0
                        options:UIViewAnimationOptionCurveEaseOut
                     animations:^{
                            //set the position
                            self.colorView.center = [[touches anyObject] locationInView:self.view];
                        }
                     completion:NULL];

记住一个原则:UIView的动画只能操作view的东西,不能操作layer层的东西,CALayer层的动画,也不要和view混着用。

缓冲和关键帧动画

我们不想给整个动画过程应用这个效果,我们希望对每个动画的过程重复这样的缓冲,于是每次颜色的变换都会有脉冲效果。

CAKeyframeAnimation有一个NSArray类型的timingFunctions属性,我们可以用它来对每次动画的步骤指定不同的计时函数。但是指定函数的个数一定要等于keyframes数组的元素个数减一,因为它是描述每一帧之间动画速度的函数。

@interface ViewController ()
@property (nonatomic, weak) IBOutlet UIView *layerView;
@property (nonatomic, weak) IBOutlet CALayer *colorLayer;
@end
@implementation ViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    //create sublayer
    self.colorLayer = [CALayer layer];
    self.colorLayer.frame = CGRectMake(50.0f, 50.0f, 100.0f, 100.0f);
    self.colorLayer.backgroundColor = [UIColor blueColor].CGColor;
    //add it to our view
    [self.layerView.layer addSublayer:self.colorLayer];
}
- (IBAction)changeColor
{
    //create a keyframe animation
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
    animation.keyPath = @"backgroundColor";
    animation.duration = 2.0;
    animation.values = @[
                         (__bridge id)[UIColor blueColor].CGColor,
                         (__bridge id)[UIColor redColor].CGColor,
                         (__bridge id)[UIColor greenColor].CGColor,
                         (__bridge id)[UIColor blueColor].CGColor ];
    //add timing function
    CAMediaTimingFunction *fn = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseIn];
    animation.timingFunctions = @[fn, fn, fn];
    //apply animation to layer
    [self.colorLayer addAnimation:animation forKey:nil];
}
@end

后记:其实你还可以自定义缓冲动画,系统那些缓冲动画还满足不了你,你可以点这里看看

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值