从Core Animation到Facebook‘s Pop(1)

来源:互联网 发布:公安大数据的深度应用 编辑:程序博客网 时间:2024/05/07 15:05

相信所有开发者在开发阶段都会接触到动画,简单的从UIView层的动画一直到layer层的动画,抑或通过重绘实现的动画。在恰当场景使用合适的动画不仅可以让你的app交互更加新奇有趣,而且能够体现出作者的实力。实在是居家旅行的必备。

其实最理想的动画应该是专门负责交互的设计师使用Quartz Composer或者AE之类的设计工具,设计完之后告诉你时间节点,动画样式之类的数据,然后你直接利用代码转换,然后据我所知,国内的大部分公司(至少9成)是没有这样的流程的,大部分动画都靠凑出来。可能是工程师通过一次次调校代码的参数调出来的。

国内的app开发者可能不是太重视这方面的开发,所以很少有给我那种第一次见到paper(facebook出品)或者是Taasky,City Guides那种震撼感觉的。

011.gif

这是Taasky的

012.gif

这是国家地理杂志出的City guide


013.jpg

这是Paper(点击查看gif图)

这个系列的博客主要讲的是Layer层动画的实现,因为View层的动画实际上并不难掌握,相信大家也都使用的很熟练了。

每个view都有一个layer,layer主要负责渲染,view只是在layer的基础上增加了Event Handle一类的东西,实际上你调整view的frame也好,调backgroundcolor也罢,这类负责展示的属性实际上都是在调整layer的对应属性。动画无非就是layer层的再次渲染。

这篇博客将通过这个例子告诉大家CABasicanimation的基本用法.

015.gif

我们的目标

看到别人的交互第一个想法应该是拆解,因为一个优秀的动画肯定不是由一个单元的效果,或者单一的时间线(timingfuntion)组成的。肯定是由多种不同的效果组成。

我们来试着拆解一下上图的圆球动画效果。

  1. 第一步最明显的肯定是小圆从小变到大。

  2. 那么我们应该可以想到是做了makescale,而且在做scale之前要先修改view的cornerRadius以使这个view变成一个圆形。

  3. 然后最明显的变化就是这个圆变成了椭圆。可能这个地方会有人断了思路,仔细想想其实不难。makescale需要传参数。

CATransform3DMakeScale(0.1, 0.1, 1)

4.  这三个参数分别代表在x,y,z轴压缩的比例,当x,y轴压缩比率相同的情况下view的宽高缩放比例相同,那么只改变Y轴缩放比例,让Y轴缩放比例大于X轴缩放比例那么一个圆不就变成了椭圆么。

5.  想到这其实第二个动画的实现也呼之欲出。我们只需要在小圆同比率变大到一定程度之后,只改变Y 轴的放大比率就行了。

我们先实现第一个拆解的动画,就是X,Y轴同比率缩放。

1
2
3
4
5
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
animation.duration = 3.;
animation.fromValue = @(0.1);
animation.toValue = @(1.);
return animation;

这个地方我想多说几句的是这个叫做animationWithKeyPath的东西。这个keyPath到底是什么?

一句话,就是CALayer的所有属性。如图展示了一部分属性

203.png

CALayer的一部分属性

这样,你们可以自己写一个CABasicAnimation 然后在keypath里分别填入下面的属性,自己试试效果。(连shadowColor都可以用basicanimation做动画哦!)

我们来看看第一个拆解动画的效果。

016.gif

然后第二个拆解动画,我们只改变Y轴压缩率。

1
2
3
4
5
6
7
8
- (CABasicAnimation *)createScaleYAnimation
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale.y"];
animation.duration = 3.;
animation.fromValue = @(1);
animation.toValue = @(2.);
return animation;
}

效果如图所示:

017.gif

那么问题来了,我们只是单独的实现了两个动画,怎么才能把他组合起来呢,而且这两个动画是有先后次序的。

很简单,苹果早已为我们准备了这个叫做CAGroupAnimation的东西。他可以组合多个CAAnimation,并且分配他们的开始时间和动画时长。

代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- (CAAnimationGroup *)createGroupAnimation
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
animation.duration = 3.;
animation.fromValue = @(0.1);
animation.toValue = @(1.);
CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"transform.scale.y"];
animation2.duration = 3.;
animation2.fromValue = @(1);
animation2.toValue = @(2.);
animation2.beginTime = 3.;
CAAnimationGroup *group = [CAAnimationGroup animation];
group.duration = 6.;
group.animations = @[animation,animation2];
return group;
}

这里唯一需要解释的可能就是animation2比animation多了一个beginTime,很简单,beginTime就是动画开始的时间,既然第一个动画持续时间是3秒,那么第二个动画应当在第一个动画结束的时候执行,那么就是第三3秒钟开始了。(当然,你也可以让两个动画同时执行,比如把beginTime设置为2,那么当第一个动画执行到2秒还没完的时候第二个动画就开始执行了。)

我们看看效果。

018.gif

现在我们完成了基本的动画,现在唯一的问题就是把动画和tableview的offset联系起来。直接贴代码。你们感受一下。

1
2
3
4
5
6
7
8
9
10
11
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSLog(@"offset is %@",NSStringFromCGPoint(_mTableView.contentOffset));
CGFloat delta = 8./-150;
if (_mTableView.contentOffset.y>-150) {
    [animationView setAnimationProgress:(_mTableView.contentOffset.y*delta)];
}else
{
    [animationView setAnimationProgress:8.];
}
}

然后我们最后的效果如下。

019.gif

最后放上我们的github地址: https://github.com/pingguo-zangqilong/CoreAnimationLesson1
(via:叶孤城的blog)

0 0