用缓动函数模拟弹簧,碰撞等动画效果

最近学习了一下用缓动函数模拟物理动画的效果,可以实现一些比较高级的动画效果,比如弹簧效果等。

1.缓动函数的动画效果是建立在CALayer层级的关键帧动画基础之上。
2.缓动函数是一系列模拟物理效果(如抛物线)方程式的统称,用以计算给定两点之间的插值。
3.两点之间插得值越多,效果越好,但是会耗费更多的性能。

说了这么多,什么是滑动函数呢?如下图,是缓动函数的各种曲线效果图:

用缓动函数模拟弹簧,碰撞等动画效果_第1张图片
easing.png

大家可以先去github上下载缓动函数第三方 EasingAnimation,链接地址:https://github.com/YouXianMing/EasingAnimation

用缓动函数模拟弹簧,碰撞等动画效果_第2张图片
Paste_Image.png

大家可以在浏览器里面看一下缓动函数的效果,如下图:

用缓动函数模拟弹簧,碰撞等动画效果_第3张图片
Paste_Image.png
用缓动函数模拟弹簧,碰撞等动画效果_第4张图片
Paste_Image.png

将鼠标移到曲线图上,即可看见红色光标相对应的移动轨迹。

好了,缓动函数介绍完了,现在开始进入正题,如何用缓动函数模拟物理动画效果,上代码。

先创建一个项目 ,将我们下载的第三方中如下四个文件拖入工程中,编译无问题。

Paste_Image.png

//创造一个红色的球状视图

    UIView *showView = [[UIView alloc    ] initWithFrame:CGRectMake(0, 0, 100, 100)];
    showView.layer.cornerRadius = 50;
    showView.layer.masksToBounds = YES;
    showView.contentMode = UIViewContentModeScaleAspectFill;
    showView.backgroundColor = [UIColor redColor];
    [self.view addSubview:showView];
}

然后创建关键帧动画(对关键帧动画不熟悉的童鞋可以去看我这篇文章 ,关键帧动画很重要,可以让动画按照我们指定的轨迹运行。)http://www.jianshu.com/p/2bdceb8844ed

CAKeyframeAnimation *keyFrameA = [CAKeyframeAnimation animation];
        keyFrameA.keyPath = @"position"; 
        keyFrameA.duration = 2.f;
    keyFrameA.values = [YXEasing calculateFrameFromPoint:showView.center toPoint:CGPointMake(50, self.view.frame.size.height - 50) func:BounceEaseOut frameCount:30 * 2];//values后面原本跟的是数组,在这里我们调用缓动函数中的calculateFrameFromPoint方法,表示一个起始点到终止点,func代表的参数是缓动函数的效果,framecount则是帧数,一般我们人眼识别的最大帧数是30帧,上面设了2秒,则乘以2
    showView.center = CGPointMake(50, self.view.frame.size.height - 50); //设置一下终点位置,让效果到终点位置停下来
    [showView.layer addAnimation:keyFrameA forKey:nil];

效果如下,碰撞效果:

用缓动函数模拟弹簧,碰撞等动画效果_第5张图片
boll.gif

再示例一个弹簧效果,比如钟表上秒针的来回抖动

    //创建一个表盘
    UIView *biaoView = [[UIView alloc ] initWithFrame:CGRectMake(0, 0, 300, 300)];
    biaoView.center  = self.view.center;
    biaoView.layer.borderWidth = 1.f;
    biaoView.layer.cornerRadius = 150;
    biaoView.layer.borderColor = [UIColor  redColor].CGColor;
    [self.view addSubview:biaoView];
//创建出layer,也就是秒针
    self.secLayer = [CALayer layer]; //secLayer是创建的全局变量
    self.secLayer.anchorPoint = CGPointMake(0, 0);//anchorPoint属性是layer的转动点,就好比一个图钉扣在纸上,纸随着图钉而转动,在这里设为最上面的起点 。不理解的话请访问网址:http://www.tuicool.com/articles/MvI7fu3
    self.secLayer.frame = CGRectMake(150, 150, 1, 150);
    self.secLayer.backgroundColor = [UIColor  blueColor].CGColor;
    [biaoView.layer addSublayer:self.secLayer];
 //创建定时器
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.f target:self selector:@selector(timerEvent) userInfo:nil repeats:YES];

//定义两个宏

//弧度转角度
#define RADIANS_TO_DEGREES(radians) ((radians) * (100.0 / M_PI))

//角度转弧度
#define DEGREES_TO_RADIANS(angle) ((angle) / 100.0 * M_PI)
- (void)timerEvent {
    static int i = 1;
  //在这里,我们要得到每秒转动的弧度
    CGFloat oldValue = DEGREES_TO_RADIANS((360 / 60) * i++);
    CGFloat newValue = DEGREES_TO_RADIANS((360 / 60) * i);
    
    CAKeyframeAnimation *keyFrameA = [CAKeyframeAnimation animation];
    keyFrameA.keyPath = @"transform.rotation.z";
    keyFrameA.duration = 0.5f; //由于表是每秒进行的,所以动画不可能用1秒,在这里我们设置动画效果为0.5秒
    keyFrameA.values = [YXEasing calculateFrameFromValue:oldValue toValue:newValue func:ElasticEaseOut frameCount:0.5 * 30];//调用calculateFrameFromValue,表示从老弧度到新弧度,这里的func用的是弹簧效果ElasticEaseOut,帧数设置为30 * 0.5
    self.secLayer.transform = CATransform3DMakeRotation(newValue, 0, 0, 1);//绕着z轴转动的newValue,让其每次动画后保持当前位置继续动画
    [self.secLayer addAnimation:keyFrameA forKey:nil];
}

效果如下


用缓动函数模拟弹簧,碰撞等动画效果_第6张图片
time.gif

缓动函数还有很多用法,主要还是看缓动函数的那张图,每种类型有三张方法,比如上面的弹簧效果,如下图:

用缓动函数模拟弹簧,碰撞等动画效果_第7张图片
Paste_Image.png

根据自己需要的效果,然后再easing.h中找到对应的func。

博主也就是起个抛砖引玉的作用,主要还是靠自己去认知,毕竟动画不是死的。

你可能感兴趣的:(用缓动函数模拟弹簧,碰撞等动画效果)