POP是Facebook开源的一个动画库,该动画库基于CADisplayLink(Mac平台上使用的CVDisplayLink))实现的独立于Core Animation之外的动画库。以每秒60帧的速度渲染动画,所以看起来会非常流畅。
创建一个POP动画需要六步,下面我们来逐一介绍:
POP提供4种动画效果,POPBasicAnimation
、POPSpringAnimation
、POPDecayAnimation
、POPCustomAnimation
。这些动画效果可以基于CALayer、CAShapeLayer、NSLayoutConstraint、UIView、UIScrollView、UITableView、UINavigationBar、UITabBar等类。
POPBasicAnimation
是一种基础动画,提供最基本的动画效果。接口方面和CABasicAniamtion很相似,使用可以提供初始值fromValue,这个 终点值toValue,动画时长duration以及决定动画节奏的timingFunction。其创建方式:
POPBasicAnimation *basicAnimation = [POPBasicAnimation animation]; // 创建动画
POPSpringAnimation
弹簧动画是Bezier曲线无法表述的,所以无法使用PopBasicAniamtion来实现。PopSpringAnimation便是专门用来实现弹簧动画的
POPSpringAnimation *springAnimation = [POPSpringAnimation animation];
springAnimation.velocity=@(1000); // change of value units per second每秒都改变属性
springAnimation.springBounciness=14; // value between 0-20 default at 4值的范围是0~20 默认为4
springAnimation.springSpeed=3; // value between 0-20 default at 4
POPDecayAnimation
基于Bezier曲线的timingFuntion同样无法表述Decay Aniamtion,所以Pop就单独实现了一个 PopDecayAnimation,用于衰减动画。衰减动画一个很常见的地方就是 UIScrollView 滑动松开后的减速当滑动手势结束时,根据结束的加速度,给衰减动画一个初始的velocity,用来决定衰减的时长。
POPDecayAnimation *decayAnimation=[POPDecayAnimation animation];
decayAnimation.velocity=@(233); //change of value units per second
decayAnimation.deceleration=.833; //range of 0 to 1
POPCustomAnimation
继承自PopAnimation用于创建自定义动画用的,通过POPCustomAnimationBlock类型的block进行初始化.
typedef BOOL (^POPCustomAnimationBlock)(id target, POPCustomAnimation *animation);
此block会在界面的每一帧更新的时候被调用,创建者需要在block中根据当前currentTime和elapsedTime来决定如何更新target的相关属性,以实现特定的动画。当你需要结束动画的时候就在block中返回NO,否则返回YES。
在创建动画的时候,我们可以直接选择动画的属性,例如
POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerScaleXY]; // 这里修改的是视图的XY上的缩放属性
View Properties 视图属性:
Layer Properties 层属性
basicAnimation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
// kCAMediaTimingFunctionLinear kCAMediaTimingFunctionEaseIn kCAMediaTimingFunctionEaseOut kCAMediaTimingFunctionEaseInEaseOut // 时间类型显示
该设置在POPDecayAnimation
、POPSpringAnimation
中是不起效果的。
View Properties:
Alpha - kPOPViewAlpha
POPBasicAnimation *basicAnimation = [POPBasicAnimation animation];
basicAnimation.property = [POPAnimatableProperty propertyWithName:kPOPViewAlpha];
basicAnimation.toValue= @(0); // scale from 0 to 1 缩放的范围0~1
Color - kPOPViewBackgroundColor
POPSpringAnimation *basicAnimation = [POPSpringAnimation animation];
basicAnimation.property = [POPAnimatableProperty propertyWithName: kPOPLayerBackgroundColor];
basicAnimation.toValue= [UIColor redColor];
Size - kPOPViewBounds
POPBasicAnimation *basicAnimation = [POPBasicAnimation animation];
basicAnimation.property = [POPAnimatableProperty propertyWithName:kPOPViewBounds];
basicAnimation.toValue=[NSValue valueWithCGRect:CGRectMake(0, 0, 90, 190)]; //first 2 values dont matter
Center - kPOPViewCenter
POPBasicAnimation *basicAnimation = [POPBasicAnimation animation];
basicAnimation.property = [POPAnimatableProperty propertyWithName:kPOPViewCenter];
basicAnimation.toValue=[NSValue valueWithCGPoint:CGPointMake(200, 200)];
Location & Size - kPOPViewFrame
POPBasicAnimation *basicAnimation = [POPBasicAnimation animation];
basicAnimation.property = [POPAnimatableProperty propertyWithName:kPOPViewFrame];
basicAnimation.toValue=[NSValue valueWithCGRect:CGRectMake(140, 140, 140, 140)];
Size - kPOPViewScaleXY
POPBasicAnimation *basicAnimation = [POPBasicAnimation animation];
basicAnimation.property = [POPAnimatableProperty propertyWithName:kPOPViewScaleXY];
basicAnimation.toValue=[NSValue valueWithCGSize:CGSizeMake(3, 2)];
Size(Scale) - kPOPViewSize
POPBasicAnimation *basicAnimation = [POPBasicAnimation animation];
basicAnimation.property = [POPAnimatableProperty propertyWithName:kPOPViewSize];
basicAnimation.toValue=[NSValue valueWithCGSize:CGSizeMake(30, 200)];
Layer Properties
Color - kPOPLayerBackgroundColor
POPSpringAnimation *basicAnimation = [POPSpringAnimation animation];
basicAnimation.property = [POPAnimatableProperty propertyWithName: kPOPLayerBackgroundColor];
basicAnimation.toValue= [UIColor redColor];
Size - kPOPLayerBounds
POPSpringAnimation *basicAnimation = [POPSpringAnimation animation];
basicAnimation.property = [POPAnimatableProperty propertyWithName: kPOPLayerBounds];
basicAnimation.toValue= [NSValue valueWithCGRect:CGRectMake(0, 0, 90, 90)]; //first 2 values dont matter
Size - kPOPLayerScaleXY
POPBasicAnimation *basicAnimation = [POPBasicAnimation animation];
basicAnimation.property = [POPAnimatableProperty propertyWithName: kPOPLayerScaleXY];
basicAnimation.toValue= [NSValue valueWithCGSize:CGSizeMake(2, 1)];//increases width and height scales
Size - kPOPLayerSize
POPBasicAnimation *basicAnimation = [POPBasicAnimation animation];
basicAnimation.property = [POPAnimatableProperty propertyWithName:kPOPLayerSize];
basicAnimation.toValue= [NSValue valueWithCGSize:CGSizeMake(200, 200)];
Opacity - kPOPLayerOpacity
POPSpringAnimation *basicAnimation = [POPSpringAnimation animation];
basicAnimation.property = [POPAnimatableProperty propertyWithName: kPOPLayerOpacity];
basicAnimation.toValue = @(0);
Position - kPOPLayerPosition
POPSpringAnimation *basicAnimation = [POPSpringAnimation animation];
basicAnimation.property = [POPAnimatableProperty propertyWithName: kPOPLayerPosition];
basicAnimation.toValue= [NSValue valueWithCGRect:CGRectMake(130, 130, 0, 0)];//last 2 values dont matter
X Position - kPOPLayerPositionX
POPSpringAnimation *basicAnimation = [POPSpringAnimation animation];
basicAnimation.property = [POPAnimatableProperty propertyWithName: kPOPLayerPositionX];
basicAnimation.toValue= @(240);
Y Position - kPOPLayerPositionY
POPSpringAnimation *anim = [POPSpringAnimation animation];
anim.property=[POPAnimatableProperty propertyWithName:kPOPLayerPositionY];
anim.toValue = @(320);
Rotation - kPOPLayerRotation
POPSpringAnimation *basicAnimation = [POPSpringAnimation animation];
basicAnimation.property = [POPAnimatableProperty propertyWithName: kPOPLayerRotation];
basicAnimation.toValue= @(M_PI/4); //2 M_PI is an entire rotation
basicAnimation.name=@"animationName"; // 这个名字根据自己的需要来添加
basicAnimation.delegate=self;
代理实现一下来监听动画执行状态:
Declare Delegate Protocol 声明代理协议
Delegate Methods 代理方法
- (void)animatorWillAnimate:(POPAnimator *)animator;将要执行动画的方法
- (void)animatorDidAnimate:(POPAnimator *)animator;执行完动画的方法
在这里我们就可以根据动画的执行状态做一些我们自己的业务了,当然我们同样可以通过block的方式来实现。
例如:
anim.completionBlock = ^(POPAnimation *anim, BOOL finished) {
if (finished) {
// do something here
}
};
例如:
[self.tableView pop_addAnimation:basicAnimation forKey:@"WhatEverNameYouWant"];
其实这一步的Key也就是我们上一步设置的Name属性,设置该名字以后,在代理方法中我们就可以根据Name值来区别动画,然后根据不同的动画执行我们需要的代码。
总结:Pop Animation应用于CALayer时,在动画运行的任何时刻,layer和其presentationLayer的相关属性值始终保持一致,而Core Animation做不到。Pop Animation可以应用任何NSObject的对象,而Core Aniamtion必须是CALayer。