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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容

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