zoukankan      html  css  js  c++  java
  • POP介绍与使用实践(快速上手动画)[转]

    前言


    动画在APP开发过程中 大家多多少少都会接触到 而且随着ios7的扁平化风格启用之后 越来越多的APP开始尝试加入各种绚丽的动画交互效果以增加APP的用户体验(当然 还是以国外的APP居多)

    有过相关开发经验的同学肯定知道在iOS中 动画相关的部分都是基于Core Animation 但是今天我们不讨论Core Animation 今天的主角是POP -来自于Facebook的动画引擎(其实我不喜欢把POP定义为动画引擎 我愿意称它为函数发生器)

    介绍


    官方地址 https://github.com/facebook/pop
    官方介绍(翻译版)

    POP是一个在iOS与OS X上通用的极具扩展性的动画引擎 它在基本的静态动画的基础上增加的弹簧动画与衰减动画 使之能创造出更真实更具物理性的交互动画 POP的API可以快速的与现有的ObjC代码集成并可以作用于任意对象的任意属性
    POP是个相当成熟且久经考验的框架 Facebook出品的令人惊叹的Paper应用中的所有动画和效果即出自POP

    安装方式还是推荐使用CocoaPod

    1
    pod 'pop', '~> 1.0'

    POP的神奇之处在于 它是独立与Core Animation的存在 所以 忘记Core Animation吧 忘记Layer Tree吧 迎接一个简单的明天 (LOL 开玩笑的~:) 很多地方还是会需要Core Animation的 不过说不定哪天苹果大发善心 将动画相关的部分向POP借鉴一点也不是不可能的(比如SpriteKit就借鉴了Cocos2D :)

    使用


    POP默认支持三种动画 但同时也支持自定义动画

    • POPBasicAnimation
    • POPSpringAnimation
    • POPDecayAnimation
    • POPCustomAnimation //自定义动画

    这里我们只讨论前三种(因为自定义动画我也没用过 :) 先来看看官方的示例代码吧

    官方代码示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    //Basic animations can be used to interpolate values over a specified time period. To use an ease-in ease-out animation to animate a view's alpha from 0.0 to 1.0 over the default duration:
    POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPViewAlpha];
    anim.fromValue = @(0.0);
    anim.toValue = @(1.0);
    [view pop_addAnimation:anim forKey:@"fade"];

    //Spring animations can be used to give objects a delightful bounce. In this example, we use a spring animation to animate a layer's bounds from its current value to (0, 0, 400, 400):
    POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerBounds];
    anim.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 400, 400)];
    [layer pop_addAnimation:anim forKey:@"size"];


    //Decay animations can be used to gradually slow an object to a halt. In this example, we decay a layer's positionX from it's current value and velocity 1000pts per second:
    POPDecayAnimation *anim = [POPDecayAnimation animationWithPropertyNamed:kPOPLayerPositionX];
    anim.velocity = @(1000.);
    [layer pop_addAnimation:anim forKey:@"slide"];

    POPBasicAnimation

    POPBasicAnimation使用最广泛 提供固定时间间隔的动画(如淡入淡出效果)

    代码示例1

    1
    2
    3
    4
    POPBasicAnimation *anBasic = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPositionX];
    anBasic.toValue = @(self.square.center.y+300);
    anBasic.beginTime = CACurrentMediaTime() + 1.0f;
    [self.square pop_addAnimation:anBasic forKey:@"position"];

    其动画效果如下
    POPBasicAnimationPOPBasicAnimation

    可以看到 添加一个动画最少仅需三步

    1. 定义一个animation对象 并指定对应的动画属性
    2. 设置初始值和默认值(初始值可以不指定 会默认从当前值开始)
    3. 添加到想产生动画的对象上

    POPBasicAnimation可配置的属性与默认值为

    1
    duration:0.4    //动画间隔

    POPBasicAnimation提供四种timingfunction(很熟悉 对不对? 就是Core Animation中那些)

    • kCAMediaTimingFunctionLinear
    • kCAMediaTimingFunctionEaseIn
    • kCAMediaTimingFunctionEaseOut
    • kCAMediaTimingFunctionEaseInEaseOut

    其时间函数分别如下

    kCAMediaTimingFunctionLinearkCAMediaTimingFunctionLinear
    kCAMediaTimingFunctionEaseInkCAMediaTimingFunctionEaseIn
    kCAMediaTimingFunctionEaseOutkCAMediaTimingFunctionEaseOut
    kCAMediaTimingFunctionEaseInEaseOutkCAMediaTimingFunctionEaseInEaseOut

    POPSpringAnimation

    POPSpringAnimation也许是大多数人使用POP的理由 其提供一个类似弹簧一般的动画效果(使用后 APP立马就活泼起来了 有木有?!)

    代码示例23

    1
    2
    3
    4
    5
    POPSpringAnimation *anSpring = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPositionX];
    anSpring.toValue = @(self.square.center.y+300);
    anSpring.beginTime = CACurrentMediaTime() + 1.0f;
    anSpring.springBounciness = 10.0f;
    [self.square pop_addAnimation:anSpring forKey:@"position"];

    其动画效果如下
    动画效果动画效果

    POPSpringAnimation可配置的属性与默认值为

    1
    2
    3
    4
    5
    springBounciness:4.0    //[0-20] 弹力 越大则震动幅度越大
    springSpeed :12.0 //[0-20] 速度 越大则动画结束越快
    dynamicsTension :0 //拉力 接下来这三个都跟物理力学模拟相关 数值调整起来也很费时 没事不建议使用哈
    dynamicsFriction:0 //摩擦 同上
    dynamicsMass :0 //质量 同上

    注意:POPSpringAnimation是没有duration字段的 其动画持续时间由以上几个参数决定

    其时间函数如下
    时间函数时间函数

    POPDecayAnimation

    POPDecayAnimation提供一个过阻尼效果(其实Spring是一种欠阻尼效果) 可以实现类似UIScrollView的滑动衰减效果(是的 你可以靠它来自己实现一个UIScrollView)

    代码示例3

    1
    2
    3
    4
    POPDecayAnimation *anDecay = [POPDecayAnimation animationWithPropertyNamed:kPOPLayerPositionX];
    anDecay.velocity = @(600);
    anDecay.beginTime = CACurrentMediaTime() + 1.0f;
    [self.square pop_addAnimation:anDecay forKey:@"position"];

    其动画效果如下
    动画效果动画效果

    注意:这里对POPDecayAnimation设置toValue是没有意义的 会被忽略(因为目的状态是动态计算得到的)

    POPDecayAnimation可配置的属性与默认值为

    1
    deceleration:0.998  //衰减系数(越小则衰减得越快)

    注意:POPDecayAnimation也是没有duration字段的 其动画持续时间由velocity与deceleration决定

    其时间函数如下
    时间函数时间函数

    接下来我们看一下POP默认支持哪些属性的动画 打开POPAnimatablePropery.h可以看到如下定义(这些是到目前为止 所支持的属性 随着版本的更新 还在不断的新增中 :)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    /**
    Common CALayer property names.
    */
    extern NSString * const kPOPLayerBackgroundColor;
    extern NSString * const kPOPLayerBounds;
    extern NSString * const kPOPLayerCornerRadius;
    extern NSString * const kPOPLayerBorderWidth;
    extern NSString * const kPOPLayerBorderColor;
    extern NSString * const kPOPLayerOpacity;
    extern NSString * const kPOPLayerPosition;
    extern NSString * const kPOPLayerPositionX;
    extern NSString * const kPOPLayerPositionY;
    extern NSString * const kPOPLayerRotation;
    extern NSString * const kPOPLayerRotationX;
    extern NSString * const kPOPLayerRotationY;
    extern NSString * const kPOPLayerScaleX;
    extern NSString * const kPOPLayerScaleXY;
    extern NSString * const kPOPLayerScaleY;
    extern NSString * const kPOPLayerSize;
    extern NSString * const kPOPLayerSubscaleXY;
    extern NSString * const kPOPLayerSubtranslationX;
    extern NSString * const kPOPLayerSubtranslationXY;
    extern NSString * const kPOPLayerSubtranslationY;
    extern NSString * const kPOPLayerSubtranslationZ;
    extern NSString * const kPOPLayerTranslationX;
    extern NSString * const kPOPLayerTranslationXY;
    extern NSString * const kPOPLayerTranslationY;
    extern NSString * const kPOPLayerTranslationZ;
    extern NSString * const kPOPLayerZPosition;
    extern NSString * const kPOPLayerShadowColor;
    extern NSString * const kPOPLayerShadowOffset;
    extern NSString * const kPOPLayerShadowOpacity;
    extern NSString * const kPOPLayerShadowRadius;

    /**
    Common CAShapeLayer property names.
    */
    extern NSString * const kPOPShapeLayerStrokeStart;
    extern NSString * const kPOPShapeLayerStrokeEnd;
    extern NSString * const kPOPShapeLayerStrokeColor;
    extern NSString * const kPOPShapeLayerFillColor;

    /**
    Common NSLayoutConstraint property names.
    */
    extern NSString * const kPOPLayoutConstraintConstant;


    #if TARGET_OS_IPHONE

    /**
    Common UIView property names.
    */
    extern NSString * const kPOPViewAlpha;
    extern NSString * const kPOPViewBackgroundColor;
    extern NSString * const kPOPViewBounds;
    extern NSString * const kPOPViewCenter;
    extern NSString * const kPOPViewFrame;
    extern NSString * const kPOPViewScaleX;
    extern NSString * const kPOPViewScaleXY;
    extern NSString * const kPOPViewScaleY;
    extern NSString * const kPOPViewSize;
    extern NSString * const kPOPViewTintColor;

    /**
    Common UIScrollView property names.
    */
    extern NSString * const kPOPScrollViewContentOffset;
    extern NSString * const kPOPScrollViewContentSize;
    extern NSString * const kPOPScrollViewZoomScale;
    extern NSString * const kPOPScrollViewContentInset;

    /**
    Common UITableView property names.
    */
    extern NSString * const kPOPTableViewContentOffset;
    extern NSString * const kPOPTableViewContentSize;

    /**
    Common UICollectionView property names.
    */
    extern NSString * const kPOPCollectionViewContentOffset;
    extern NSString * const kPOPCollectionViewContentSize;

    /**
    Common UINavigationBar property names.
    */
    extern NSString * const kPOPNavigationBarBarTintColor;

    /**
    Common UIToolbar property names.
    */
    extern NSString * const kPOPToolbarBarTintColor;

    /**
    Common UITabBar property names.
    */
    extern NSString * const kPOPTabBarBarTintColor;

    /**
    Common UILabel property names.
    */
    extern NSString * const kPOPLabelTextColor;

    作为刚接触POP的一些同学来说 如果在上面看到你希望的某些属性的话 你可以像官方代码示例一样指定这个属性即可开始动画了
    但是如果你想要的某些属性不在之上呢 这时候自定义属性POPAnimatableProperty就排上用场了

    自定义属性

    POP默认支持的三种动画都继承自POPPropertyAnimation POPPropertyAnimation中定义了一个叫property的属性( 之前没有用到它是因为POP根据不同的默认动画属性帮你生成了默认的property) 而这个property则是用来驱动POP的动画效果中的重要一环

    代码示例4

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    POPAnimatableProperty *prop = [POPAnimatableProperty propertyWithName:@"prop" initializer:^(POPMutableAnimatableProperty *prop) {
    // read value
    prop.readBlock = ^(id obj, CGFloat values[]) {

    };
    // write value
    prop.writeBlock = ^(id obj, const CGFloat values[]) {

    };
    // dynamics threshold
    prop.threshold = 0.01;
    }];

    其组成就是一个readBlock一个writeBlock和一个threashold

    • readBlock告诉POP当前的属性值
    • writeBlock中修改变化后的属性值
    • threashold决定了动画变化间隔的阈值 值越大writeBlock的调用次数越少

    POPAnimatableProperty其实是POP中一个比较重要的东西 像上面提到的POP自带的动画属性 查看源代码可以看到也只是POP自动帮你设置好了POPAnimatableProperty而已 其作用就是当动画的某个时间片被触发时 告诉系统如何根据当前时间片做出变化

    还是以一个实际的例子来说明如何使用自定义属性 比如我们要实现一个像系统的时钟APP里秒表计时的一个效果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    POPAnimatableProperty *prop = [POPAnimatableProperty propertyWithName:@"countdown" initializer:^(POPMutableAnimatableProperty *prop) {

    prop.writeBlock = ^(id obj, const CGFloat values[]) {
    UILabel *lable = (UILabel*)obj;
    label.text = [NSString stringWithFormat:@"%02d:%02d:%02d",(int)values[0]/60,(int)values[0]%60,(int)(values[0]*100)%100];
    };

    // prop.threshold = 0.01f;
    }];

    POPBasicAnimation *anBasic = [POPBasicAnimation linearAnimation]; //秒表当然必须是线性的时间函数
    anBasic.property = prop; //自定义属性
    anBasic.fromValue = @(0); //从0开始
    anBasic.toValue = @(3*60); //180秒
    anBasic.duration = 3*60; //持续3分钟
    anBasic.beginTime = CACurrentMediaTime() + 1.0f; //延迟1秒开始
    [label pop_addAnimation:anBasic forKey:@"countdown"];

    其动画效果如下
    动画效果动画效果

    有没有从中得到一些启发呢? POP可以做的事情可远比Core Animation要多(注意这里我们使用了beginTime这个属性来设置动画的延迟施放) 例如音乐播放时那种淡入淡出的效果等等也可以用POP来实现

    小结


    其实只需要熟练掌握POP自带的三种动画 即可完成大部分的动画效果 如果实在是无法满足你的需求的话 自定义动画也基本可以满足你的要求 可以说POP化繁为简的出现 极大的方便了我们这些苦逼的coder

    当然 就像我说的 POP不仅仅是一个动画引擎 相信经过我最后一个例子 大家可以得到一点启事 POP能做的事情还不少 :)

    from:http://adad184.com/2015/03/11/intro-to-pop/

  • 相关阅读:
    JavaScript数据结构和算法----队列
    JavaScript数据结构和算法----栈
    ES6箭头函数
    JavaScript的错误处理
    easing--缓动函数--贝塞尔函数--圆盘转动抽奖应用
    node之子线程child_process模块
    node上传文件并在网页中展示
    Python内置函数之int()
    从Python的角度来看编码与解码
    关于.pyc文件
  • 原文地址:https://www.cnblogs.com/sunshine-anycall/p/4812805.html
Copyright © 2011-2022 走看看