版本记录
版本号 | 时间 |
---|---|
V1.0 | 2017.12.17 |
前言
POP
框架是
1. Facebook Pop动画框架详细解析(一) —— 基本概览
2. Facebook Pop动画框架详细解析(二) —— 基本架构
几个重要参数
下面我们看一下springAnimation
几个重要参数。
-
Bounciness
反弹-影响动画作用的参数的变化幅度 -
Speed
速度 -
Tension
拉力-影响回弹力度以及速度 -
Friction
摩擦力-如果开启,动画会不断重复,幅度逐渐削弱,直到停止。 -
Mass
质量-细微的影响动画的回弹力度以及速度
这里,我们使用 pop_addAnimation
来让动画开始生效,如果你想删除动画的话,那么你需要调用 pop_removeAllAnimations
。 与 iOS 自带的动画不同,如果你在动画的执行过程中删除了物体的动画,那么物体会停在动画状态的最后一个瞬间,而不是闪回开始前的状态。
功能实现
下面我们就看一下功能实现,还是直接看代码。
1. ViewController.m
#import "ViewController.h"
#import "POP.h"
#import "PDAnimationManager.h"
@interface ViewController () <UITableViewDelegate, UITableViewDataSource>
@property (weak, nonatomic) IBOutlet UISlider *bounceSlider;
@property (strong, nonatomic) IBOutlet UISlider *speedSlider;
@property (strong, nonatomic) IBOutlet UISwitch *tensionSwitch;
@property (strong, nonatomic) IBOutlet UISlider *tensionSlider;
@property (weak, nonatomic) IBOutlet UISwitch *FrictionSwitch;
@property (weak, nonatomic) IBOutlet UISlider *frictionSlider;
@property (weak, nonatomic) IBOutlet UISwitch *massSwitch;
@property (weak, nonatomic) IBOutlet UISlider *massSlider;
@property (nonatomic, strong) UITableView * tableView;
@property (nonatomic, assign) CGFloat bouncinessValue;
@property (nonatomic, assign) CGFloat speedTweakValue;
@property (nonatomic, strong) CALayer *popCircle;
@property (nonatomic, assign) BOOL animated;
@property (nonatomic, strong) NSString *animationType;
@property (nonatomic, strong) NSArray *animationTypes;
@property (nonatomic, copy) NSString *exampleID;
@end
@implementation ViewController
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
self.tableView.center = CGPointMake(self.view.center.x, self.view.center.y - 1000.0);
[self.tableView setContentInset:UIEdgeInsetsMake(66,0,0,0)];
self.animationType = kPOPLayerScaleXY;
[self setPopCircle];
[self.view addSubview:self.tableView];
}
#pragma mark - Object Private Function
- (void)setPopCircle
{
self.popCircle = [CALayer layer];
[self resetCircle];
[self.view.layer addSublayer:self.popCircle];
self.animationTypes = @[kPOPLayerBackgroundColor,kPOPLayerBounds,kPOPLayerOpacity,kPOPLayerPosition,kPOPLayerRotation,
kPOPLayerScaleXY,kPOPLayerSize,kPOPLayerTranslationXY,kPOPLayerRotationX, kPOPLayerRotationY];
self.tableView.dataSource = self;
self.tableView.delegate = self;
[self.tableView reloadData];
}
- (void)resetCircle
{
[self.popCircle pop_removeAllAnimations];
self.popCircle.opacity = 1.0;
self.popCircle.transform = CATransform3DIdentity;
[self.popCircle setMasksToBounds:YES];
[self.popCircle setBackgroundColor:[UIColor redColor].CGColor];
[self.popCircle setCornerRadius:25.0f];
[self.popCircle setBounds:CGRectMake(0.0f, 0.0f, 50.0f, 50.0f)];
self.popCircle.position = CGPointMake(self.view.center.x, 180.0);
}
- (void)hideTableView
{
[self resetCircle];
POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
anim.toValue = [NSValue valueWithCGPoint:CGPointMake(self.view.window.center.x, -1000.0)];
[self.tableView pop_addAnimation:anim forKey:@"AnimationHide"];
anim.completionBlock = ^(POPAnimation *anim, BOOL finished) {
if (finished) {
[self performAnimation];
}
};
}
- (void)setAnimationWithBounciness:(CGFloat)bounciness andSpeed:(CGFloat)speed
{
[self.popCircle pop_removeAllAnimations];
POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:self.animationType];
[PDAnimationManager springObject:self.popCircle configAnimation:anim WithType:self.animationType andAnimated:self.animated];
self.animated = !self.animated;
anim.springBounciness = bounciness;
anim.springSpeed = speed;
if (self.FrictionSwitch.isOn) {
anim.dynamicsFriction = self.frictionSlider.value;
}
if (self.tensionSwitch.isOn) {
anim.dynamicsTension = self.tensionSlider.value;
}
if (self.massSwitch.isOn) {
anim.dynamicsMass = self.massSlider.value;
}
anim.completionBlock = ^(POPAnimation *anim, BOOL finished) {
if (finished) {
[self performAnimation];
}
};
[self.popCircle pop_addAnimation:anim forKey:@"Animation"];
}
- (void)performAnimation
{
[self setAnimationWithBounciness:self.bounceSlider.value andSpeed:self.speedSlider.value];
}
#pragma mark - Action && Notification
- (IBAction)showEffect:(id)sender
{
[self resetCircle];
if (self.tableView.center.y > 0) {
[self hideTableView];
}
else{
POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
anim.toValue = [NSValue valueWithCGPoint:self.view.center];
[self.tableView pop_addAnimation:anim forKey:@"AnimationShow"];
}
}
- (IBAction)sliderValueChanged:(id)sender
{
[self resetCircle];
[self performAnimation];
}
#pragma mark - UITableViewDelegate, UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.animationTypes count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"UITableViewCell"];
cell.textLabel.text = [self.animationTypes objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.animationType = [self.animationTypes objectAtIndex:indexPath.row];
[self hideTableView];
}
@end
2. PDAnimationManager.h
#import <UIKit/UIKit.h>
#import <POP/POP.h>
@interface PDAnimationManager : NSObject
+ (void)springObject:(CALayer*)layer configAnimation:(POPPropertyAnimation *)animation WithType:(NSString *)type andAnimated:(BOOL)animated;
+ (void)decayObject:(CALayer*)layer configAnimation:(POPDecayAnimation *)animation WithType:(NSString *)type andAnimated:(BOOL)animated andVelocitySlider:(UISlider *)slider;
@end
3.PDAnimationManager.m
#import "PDAnimationManager.h"
@implementation PDAnimationManager
+ (void)springObject:(CALayer*)layer configAnimation:(POPPropertyAnimation *)animation WithType:(NSString *)type andAnimated:(BOOL)animated
{
//For scale
if ([type isEqualToString:kPOPLayerScaleXY]) {
if (animated) {
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(1.0, 1.0)];
}
else{
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(2.0, 2.0)];
}
}
else if ([type isEqualToString:kPOPLayerBackgroundColor])
{
if (animated) {
animation.toValue = [UIColor purpleColor];
}
else{
animation.toValue = [UIColor colorWithRed:0.16 green:0.72 blue:1 alpha:1];
}
}
else if ([type isEqualToString:kPOPLayerBounds])
{
if (animated) {
animation.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 30, 30)];
}
else{
animation.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 150, 150)];
}
}
else if ([type isEqualToString:kPOPLayerOpacity])
{
if (animated) {
animation.toValue = @0;
}
else{
animation.toValue = @1.0;
}
}
else if ([type isEqualToString:kPOPLayerPosition])
{
if (animated) {
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(60, 150)];
}
else{
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(260, 150)];
}
}
else if ([type isEqualToString:kPOPLayerRotation])
{
layer.cornerRadius = 10.0;
if (animated) {
animation.toValue = @(M_PI_2);
}
else{
animation.toValue = @(0);
}
}
else if ([type isEqualToString:kPOPLayerSize])
{
if (animated) {
animation.toValue = [NSValue valueWithCGSize:CGSizeMake(50.0, 100.0)];
}
else{
animation.toValue = [NSValue valueWithCGSize:CGSizeMake(50.0, 50)];
}
}
else if ([type isEqualToString:kPOPLayerTranslationXY])
{
if (animated) {
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(100.0f,0.0f)];
}
else{
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(-100.0f,0.0f)];
}
}
else if ([type isEqualToString:kPOPLayerRotationX])
{
if (animated) {
animation.toValue = @(M_PI_2);
}
else{
animation.toValue = @(0);
}
}
else if ([type isEqualToString:kPOPLayerRotationY])
{
if (animated) {
animation.toValue = @(M_PI_2);
}else{
animation.toValue = @(0);
}
}
}
+ (void)decayObject:(CALayer*)layer configAnimation:(POPDecayAnimation *)animation WithType:(NSString *)type andAnimated:(BOOL)animated andVelocitySlider:(UISlider *)slider;
{
//For scale
if ([type isEqualToString:kPOPLayerScaleXY]) {
if (animated) {
animation.velocity = [NSValue valueWithCGSize:CGSizeMake(-slider.value/100.0, -slider.value/100.0)];
}
else{
animation.velocity = [NSValue valueWithCGSize:CGSizeMake(slider.value/100.0, slider.value/100.0)];
animation.fromValue = [NSValue valueWithCGSize:CGSizeMake(0.5, 0.5)];
}
}
else if ([type isEqualToString:kPOPLayerBackgroundColor])
{
if (animated) {
animation.velocity = [UIColor colorWithRed:-slider.value/100.0 green:-slider.value/200.0 blue:-slider.value/300.0 alpha:1.0];
}
else{
animation.velocity = [UIColor colorWithRed:slider.value/100.0 green:slider.value/200.0 blue:slider.value/300.0 alpha:1.0];
animation.fromValue = [UIColor colorWithRed:0.2 green:0.1 blue:0.3 alpha:1];
}
}
else if ([type isEqualToString:kPOPLayerBounds])
{
if (animated) {
animation.velocity = [NSValue valueWithCGRect:CGRectMake(0, 0, -slider.value, -slider.value)];
}
else{
animation.velocity = [NSValue valueWithCGRect:CGRectMake(0, 0, slider.value, slider.value)];
animation.fromValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 50.0, 50.0)];
}
}
else if ([type isEqualToString:kPOPLayerOpacity])
{
if (animated) {
animation.velocity = @(-slider.value/50.0);
}
else{
animation.velocity = @(slider.value/50.0);
animation.fromValue = @0.0;
}
}
else if ([type isEqualToString:kPOPLayerPosition])
{
if (animated) {
animation.velocity = [NSValue valueWithCGPoint:CGPointMake(-slider.value, -slider.value)];
}
else{
animation.velocity = [NSValue valueWithCGPoint:CGPointMake(slider.value, slider.value)];
animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(160, 150)];
}
}
else if ([type isEqualToString:kPOPLayerPositionX])
{
if (animated) {
animation.velocity = @(-slider.value);
}
else{
animation.velocity = @(slider.value);
animation.fromValue = @(25.0);
}
}
else if ([type isEqualToString:kPOPLayerRotation])
{
layer.cornerRadius = 10.0;
if (animated) {
animation.velocity = @(-slider.value);
}
else{
animation.velocity = @(slider.value);
animation.fromValue = @(M_PI_2);
}
}
else if ([type isEqualToString:kPOPLayerSize])
{
if (animated) {
animation.velocity = [NSValue valueWithCGSize:CGSizeMake(-slider.value/10.0, -slider.value*3)];
}
else{
animation.velocity = [NSValue valueWithCGSize:CGSizeMake(slider.value/10.0, slider.value*3)];
animation.fromValue = [NSValue valueWithCGSize:CGSizeMake(50.0, 50.0)];
}
}
else if ([type isEqualToString:kPOPLayerTranslationXY])
{
if (animated) {
animation.velocity = [NSValue valueWithCGPoint:CGPointMake(-slider.value, -slider.value)];
}
else{
animation.velocity = [NSValue valueWithCGPoint:CGPointMake(slider.value, slider.value)];
animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0.0f,0.0f)];
}
}
else if ([type isEqualToString:kPOPLayerRotationX])
{
if (animated) {
animation.velocity = @(-slider.value/10.0);
}
else{
animation.velocity = @(slider.value/10.0);
animation.fromValue = @(0);
}
}
else if ([type isEqualToString:kPOPLayerRotationY])
{
if (animated) {
animation.velocity = @(-slider.value/10.0);
}
else{
animation.velocity = @(slider.value/10.0);
animation.fromValue = @(0);
}
}
}
@end
功能效果
下面我们就看一下功能效果。
参考文章
1. Facebook POP 进阶指南
2. pop-handapp
后记
未完,待续~~~