POP

一、简介

POP 动画极为流畅,其秘密就在于这个 Engine 中的POPAnimator 里,POP 通过 CADisplayLink 高达 60 FPS 的特性,打造了一个游戏级的动画引擎。
源码:https://github.com/facebook/pop

二、基本用法

POPSpringAnimation 有弹性效果的动画类(个人比较喜欢这个)
POPBasicAnimation 基本动画类
POPDecayAnimation 衰减动画类
POPCustomAnimation 可以自定义动画的类
1.POPBasicAnimation

NSInteger height = CGRectGetHeight(self.view.bounds); 
NSInteger width = CGRectGetWidth(self.view.bounds); 
 
CGFloat centerX = arc4random() % width; 
CGFloat centerY = arc4random() % height; 
 
POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter]; 
anim.toValue = [NSValue valueWithCGPoint:CGPointMake(centerX, centerY)]; 
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
anim.duration = 0.4; 
[self.testView pop_addAnimation:anim forKey:@"centerAnimation"];

2.POPSpringAnimation

1.springBounciness 弹簧弹力 取值范围为[0, 20],默认值为4
2.springSpeed 弹簧速度,速度越快,动画时间越短 [0, 20],默认为12,和springBounciness一起决定着弹簧动画的效果
3.dynamicsTension 弹簧的张力
4.dynamicsFriction 弹簧摩擦
5.dynamicsMass 质量 。张力,摩擦,质量这三者可以从更细的粒度上替代springBounciness和springSpeed
POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter]; 
 
NSInteger height = CGRectGetHeight(self.view.bounds); 
NSInteger width = CGRectGetWidth(self.view.bounds); 
 
CGFloat centerX = arc4random() % width; 
CGFloat centerY = arc4random() % height; 
 
anim.toValue = [NSValue valueWithCGPoint:CGPointMake(centerX, centerY)]; 
anim.springBounciness = 16; 
anim.springSpeed = 6; 
[self.testView pop_addAnimation:anim forKey:@"center"]; 

3.POPDecayAnimation

velocity 也是必须和你操作的属性有相同的结构,如果你操作的是 bounds,想实现一个水滴滴到桌面的扩散效果,那么应该是 [NSValue valueWithCGRect:CGRectMake(0, 0,20.0, 20.0)]
如果 velocity 是负值,那么就会反向递减。
deceleration (负加速度) 是一个你会很少用到的值,默认是就是我们地球的 0.998

POPDecayAnimation *anim = [POPDecayAnimation animWithPropertyNamed:kPOPLayerPositionX]; 
anim.velocity = @(100.0); 
anim.fromValue =  @(25.0); 
//anim.deceleration = 0.998; 
anim.completionBlock = ^(POPAnimation *anim, BOOL finished) { 
  if (finished) {NSLog(@"Stop!");}}; 

三、发布界面的弹出效果

#import "XMGPublishViewController.h"
#import "TWVerticalButton.h"
#import "TWPostWordViewController.h"
#import "TWPostBlogViewController.h"
#import "TWPostPictureViewController.h"
#import "TWNavigationController.h"
#import <POP.h>
#import <AFNetworking.h>
#import <SVProgressHUD.h>

static CGFloat const XMGAnimationDelay = 0.1;
static CGFloat const XMGSpringFactor = 10;

@interface XMGPublishViewController ()
@end

@implementation XMGPublishViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self cheakNetworkStatus];
    // 让控制器的view不能被点击
    self.view.userInteractionEnabled = NO;
    
    // 数据
    NSArray *images = @[@"publish-text", @"publish-picture", @"publish-text"];
    NSArray *titles = @[@"发说说", @"发图片", @"发日志"];
    
    // 中间的6个按钮
    int maxCols = 3;
    CGFloat buttonW = 72;
    CGFloat buttonH = buttonW + 30;
    CGFloat buttonStartY = (TWScreenH - buttonH) * 0.5;
    CGFloat buttonStartX = 20;
    CGFloat xMargin = (TWScreenW - 2 * buttonStartX - maxCols * buttonW) / (maxCols - 1);
    for (int i = 0; i<images.count; i++) {
        TWVerticalButton *button = [[TWVerticalButton alloc] init];
        button.tag = i;
        [button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:button];
        // 设置内容
        button.titleLabel.font = [UIFont systemFontOfSize:14];
        [button setTitle:titles[i] forState:UIControlStateNormal];
        [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [button setImage:[UIImage imageNamed:images[i]] forState:UIControlStateNormal];
        
        // 计算X\Y
        int row = i / maxCols;
        int col = i % maxCols;
        CGFloat buttonX = buttonStartX + col * (xMargin + buttonW);
        CGFloat buttonEndY = buttonStartY + row * buttonH;
        CGFloat buttonBeginY = buttonEndY - TWScreenH;
        
        // 按钮动画
        POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPViewFrame];
        anim.fromValue = [NSValue valueWithCGRect:CGRectMake(buttonX, buttonBeginY, buttonW, buttonH)];
        anim.toValue = [NSValue valueWithCGRect:CGRectMake(buttonX, buttonEndY, buttonW, buttonH)];
        anim.springBounciness = XMGSpringFactor;
        anim.springSpeed = XMGSpringFactor;
        anim.beginTime = CACurrentMediaTime() + XMGAnimationDelay * i;
        [button pop_addAnimation:anim forKey:nil];
    }
    
    // 添加标语
    CGFloat centerX = TWScreenW * 0.5;
    CGFloat centerEndY = TWScreenH * 0.2;
    CGFloat centerBeginY = centerEndY - TWScreenH;
    UIImageView *sloganView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"app_slogan"]];
    sloganView.center = CGPointMake(centerX, centerBeginY);
    [self.view addSubview:sloganView];
    
    // 标语动画
    POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
    
    anim.fromValue = [NSValue valueWithCGPoint:CGPointMake(centerX, centerBeginY)];
    anim.toValue = [NSValue valueWithCGPoint:CGPointMake(centerX, centerEndY)];
    anim.beginTime = CACurrentMediaTime() + images.count * XMGAnimationDelay;
    anim.springBounciness = XMGSpringFactor;
    anim.springSpeed = XMGSpringFactor;
    [anim setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
        // 标语动画执行完毕, 恢复点击事件
        self.view.userInteractionEnabled = YES;
    }];
    [sloganView pop_addAnimation:anim forKey:nil];
}

- (void)cheakNetworkStatus{
    // 1.获得网络监控的管理者
    AFNetworkReachabilityManager *mgr = [AFNetworkReachabilityManager sharedManager];
    
    // 2.设置网络状态改变后的处理
    [mgr setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        // 当网络状态改变了, 就会调用这个block
        switch (status) {
            case AFNetworkReachabilityStatusUnknown: // 未知网络
                NSLog(@"未知网络");
                break;
                
            case AFNetworkReachabilityStatusNotReachable: // 没有网络(断网)
                [SVProgressHUD showImage:nil status:@"请连接网络"];
                break;
                
            case AFNetworkReachabilityStatusReachableViaWWAN: // 手机自带网络
                NSLog(@"手机自带网络");
                break;
                
            case AFNetworkReachabilityStatusReachableViaWiFi: // WIFI
                NSLog(@"WIFI");
                break;
        }
    }];
    
    // 3.开始监控
    [mgr startMonitoring];
}

- (void)buttonClick:(UIButton *)button
{
    [self cancelWithCompletionBlock:^{
        if (button.tag == 0) {
            TWPostWordViewController *postWord = [[TWPostWordViewController alloc] init];
            TWNavigationController *nav = [[TWNavigationController alloc] initWithRootViewController:postWord];
            
            UIViewController *root = [UIApplication sharedApplication].keyWindow.rootViewController;
            [root presentViewController:nav animated:YES completion:nil];
        }else if(button.tag == 1){
            TWPostPictureViewController *postWord = [[TWPostPictureViewController alloc] init];
            TWNavigationController *nav = [[TWNavigationController alloc] initWithRootViewController:postWord];
            
            UIViewController *root = [UIApplication sharedApplication].keyWindow.rootViewController;
            [root presentViewController:nav animated:YES completion:nil];
        
        
        
        
        }else if(button.tag == 2){
            TWPostBlogViewController *postWord = [[TWPostBlogViewController alloc] init];
            TWNavigationController *nav = [[TWNavigationController alloc] initWithRootViewController:postWord];
            
            UIViewController *root = [UIApplication sharedApplication].keyWindow.rootViewController;
            [root presentViewController:nav animated:YES completion:nil];
        }else {
            
        }
        
        
    }];
}

- (IBAction)cancel {
    [self cancelWithCompletionBlock:nil];
}

/**
 * 先执行退出动画, 动画完毕后执行completionBlock
 */
- (void)cancelWithCompletionBlock:(void (^)())completionBlock
{
    // 让控制器的view不能被点击
    self.view.userInteractionEnabled = NO;
    
    int beginIndex = 2;
    
    for (int i = beginIndex; i<self.view.subviews.count; i++) {
        UIView *subview = self.view.subviews[i];
        
        // 基本动画
        POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter];
        CGFloat centerY = subview.centerY + TWScreenH;
        // 动画的执行节奏(一开始很慢, 后面很快)
        //        anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
        anim.toValue = [NSValue valueWithCGPoint:CGPointMake(subview.centerX, centerY)];
        anim.beginTime = CACurrentMediaTime() + (i - beginIndex) * XMGAnimationDelay;
        [subview pop_addAnimation:anim forKey:nil];
        
        // 监听最后一个动画
        if (i == self.view.subviews.count - 1) {
            [anim setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
                [self dismissViewControllerAnimated:NO completion:nil];
                
                // 执行传进来的completionBlock参数
                !completionBlock ? : completionBlock();
            }];
        }
    }
}

/**
 pop和Core Animation的区别
 1.Core Animation的动画只能添加到layer上
 2.pop的动画能添加到任何对象
 3.pop的底层并非基于Core Animation, 是基于CADisplayLink
 4.Core Animation的动画仅仅是表象, 并不会真正修改对象的frame\size等值
 5.pop的动画实时修改对象的属性, 真正地修改了对象的属性
 */
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self cancelWithCompletionBlock:nil];
}
@end

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • IOS FACEBOOK POP动画详解 POP框架介绍 POP 的架构 架构知识了解下就行 POP 目前由四部...
    leonardni阅读 8,259评论 0 11
  • 一丶介绍 官方地址:https://github.com/facebook/pop POP是一个在iOS与OS X...
    丶纳凉阅读 5,480评论 0 3
  • pop是Facebook在开源的一款动画引擎,看下其官方的介绍: Pop是一款在iOS、tvOS和OS X平台通用...
    树下老男孩阅读 8,795评论 3 46
  • 近期对 FaceBook 的 POP 动画引擎由黑转粉😄,做个简单小结。不足之处望补充! POP 是由 Kimon...
    StarkShen阅读 3,505评论 0 1
  • 戴建东 题记:塔岩峰位于省级风景区九峰山西侧,与九峰岩遥相呼应,是九峰景区的重要辅助景点,相传此地曾经是古姑蔑国旧...
    风雅田园阅读 4,645评论 4 31