AXAnimationChain 0.4.1

AXAnimationChain 0.4.1

测试已测试
语言语言 Obj-CObjective C
许可证 MIT
发布最后发布2017年4月

devedbox维护。



  • 作者:
  • devedbox

摘要

AXAnimationChain是一个链式动画库,可以用来轻松地创建基于CAAnimation的链式动画。的组合方式有两种,一种是组合,另一种则是链接,通过以上两种方式创建的动画,既可以同时进行,也可以按时间先后进行,可以使用较少的代码创建出丰富复杂的动画效果:

简单使用:

_transitionView.spring.centerBy(CGPointMake(0, 100)).easeOut.spring.sizeBy(CGSizeMake(100, 100)).spring.cornerRadiusBy(4).animate();

SimpleSample

高级使用:

_transitionView.chainAnimator.basic.target(self).complete(@selector(complete:)).property(@"position").toValue([NSValue valueWithCGPoint:CGPointMake(100, self.view.center.y)]).easeInBack.duration(0.5).combineSpring.target(self).complete(@selector(complete:)).property(@"bounds").toValue([NSValue valueWithCGRect:CGRectMake(0, 0, 100, 100)]).duration(0.5).repeatCount(5).autoreverses.combineSpring.target(self).complete(@selector(complete:)).property(@"transform.rotation").toValue(@(M_PI_4)).duration(0.5).repeatCount(3).beginTime(1.0).autoreverses.nextToBasic.property(@"position").toValue([NSValue valueWithCGPoint:self.view.center]).duration(0.5).combineSpring.property(@"bounds").toValue([NSValue valueWithCGRect:CGRectMake(0, 0, 100, 100)]).duration(0.8).nextToBasic.property(@"transform.rotation").toValue(@(M_PI_4)).duration(1.0).completeWithBlock(nil).animate();

看起来比较冗余,但是仔细阅读会发现,其实就只有一行代码

sample

链接组合在协议AXAnimatorChainDelegate中进行定义,分别是:nextTo:combineWith:,在使用过程中应当注意区分。

AXAnimationChain基于CoreAnimation定义了几种AnimatorAXChainAnimator是基类,预定义了一系列Animate操作,可以链接组合并控制动画完成的回调

AXChainAnimator
  --AXBasicChainAnimator     ==CABasicAnimation
    --AXSpringChainAnimator  ==CASpringAnimation
  --AXKeyframeChainAnimator  ==CAKeyframeAnimation
  --AXTransitionChainAnimator==CATransitionAnimation

Next-To

通过链接的方式处理两个animator,被链接的animator将会在前者动画(包含组合的动画)完成后进行动画。大概的示例如下:

[former nextTo:nexter];

Next-To方法的原型如下:

- (instancetype)nextTo:(id<AXAnimatorChainDelegate>)animator;

当向former animator发送nextTo:消息后,返回的是nexter animator作为下次链接组合操作的对象,因此AXAnimationChain定义了几种常用的操作:

/// 链接到Basic动画并且返回链接的Basic动画.
- (AXBasicChainAnimator *)nextToBasic;
/// 链接到Spring动画并且放回链接的Spring动画.
- (AXSpringChainAnimator *)nextToSpring;
/// 链接到Keyframe动画并且放回链接的Keyframe动画.
- (AXKeyframeChainAnimator *)nextToKeyframe;
/// 链接到Transition动画并且返回链接的Transition动画.
- (AXTransitionChainAnimator *)nextToTransition;

在执行消息发送后分别返回相应类型的可操作对象。

Combine-With

通过组合的方式处理两个animator,被组合的animator将与前者动画同时进行,完成时间以最长的为准,示例如下:

[former combineWith:combiner];

Combine-With方法原型如下:

- (instancetype)combineWith:(nonnull AXChainAnimator *)animator;

当向former animator发送combineWith:消息后,返回的是combiner animator作为下次链接组合操作的对象。在AXAnimationChain中,默认以下几种组合方式:

/// 组合到Basic动画并且返回组合的Basic动画.
- (AXBasicChainAnimator *)combineBasic;
/// 组合到Spring动画并且放回组合的Spring动画.
- (AXSpringChainAnimator *)combineSpring;
/// 组合到Keyframe动画并且放回组合的Keyframe动画.
- (AXKeyframeChainAnimator *)combineKeyframe;
/// 组合到Transition动画并且返回组合的Transition动画.
- (AXTransitionChainAnimator *)combineTransition;

同样的,向某个操作对象animator发送以上消息后,将分别返回相应类型的可操作对象。

关系

AXAnimationChain中,关系的管理采用二叉树的理论。一个animator对应的类结构中包含了指向父节点superAnimator用于表示父animator,表示此animatorsuperAnimator所链接的animator,此时,superAnimatorchildAnimator即指向此animator作为一个闭环链将两者的关系锁定起来;同样的,某一个animator还拥有一个指向兄弟节点NSArray结构:combinedAnimators用于管理所组合的animator,并且,被组合的animator的父节点superAnimator则指向当前animator

- (void)start {
    NSAssert(_animatedView, @"Animation chain cannot be created because animated view is null.");
    AXChainAnimator *superAnimator = _superAnimator;
    AXChainAnimator *superSuperAnimator = _superAnimator;
    while (superAnimator) {
        superAnimator = superAnimator.superAnimator;
        if (superAnimator) {
            superSuperAnimator = superAnimator;
        }
    }
    if (superSuperAnimator) {
        [superSuperAnimator start];
    } else {
        [self _beginAnimating];
        if (!_childAnimator) [self _clear];
    }
}

AXAnimationChain就是通过这样的关系将所有链接组合animator管理起来。在完成关系的链接或组合后,需要向最后一个animator发送-start消息才能进行动画。当接收到-start消息时,会逐级遍历superAnimator直至superAnimator.superAnimator==nil,此时获取到superSuperAnimator,从superSuperAnimator自祖先往下逐级进行动画,组合的动画将同时进行,而链接的动画将顺序进行。

特性

  • 轻量级解决方案
  • 基于CoreAnimation封装,安全、高效!
  • 一行代码即可搞定复杂的动画管理,提高代码维护效率。

时间控制

时间曲线,时间曲线用于描述动画随时间进行的速度。除了包含系统默认的时间曲线之外,AXAnimationChain还提供了以下曲线以呈现更完美的动画:

http://ww1.sinaimg.cn/large/d2297bd2gw1fbmrilba19j21c610047c.jpg

AXSpringAnimation

CoreAnimation自iOS2.0起就为iOS平台提供了核心动画支持,但在iOS9.0之前,并没有提供Spring动画。要使用Spring动画,要么使用第三方动画库,要么使用系统提供的方法。

+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

但系统提供的这个方法也是从iOS7.0才开始支持使用的,并且在控制上并不那么容易。

AXSpringAnimation是基于阻尼震动运动模型的Spring动画类,能够完美与CASpringAnimation兼容:

SpringSample

动画中,左边正方形使用的是CASpringAnimation类,右边的则使用的是AXSpringAnimation,两者的动画曲线是一致的。

同样地,AXSpringAnimation的API和CASpringAnimation也是一致的:

@interface AXSpringAnimation : CAKeyframeAnimation
/* The mass of the object attached to the end of the spring. Must be greater
 than 0. Defaults to one. */

@property(assign, nonatomic) CGFloat mass;

/* The spring stiffness coefficient. Must be greater than 0.
 * Defaults to 100. */

@property(assign, nonatomic) CGFloat stiffness;

/* The damping coefficient. Must be greater than or equal to 0.
 * Defaults to 10. */

@property(assign, nonatomic) CGFloat damping;

/* The initial velocity of the object attached to the spring. Defaults
 * to zero, which represents an unmoving object. Negative values
 * represent the object moving away from the spring attachment point,
 * positive values represent the object moving towards the spring
 * attachment point. */

@property(assign, nonatomic) CGFloat initialVelocity;

/* Returns the estimated duration required for the spring system to be
 * considered at rest. The duration is evaluated for the current animation
 * parameters. */

@property(readonly, nonatomic) CFTimeInterval settlingDuration;

/* The objects defining the property values being interpolated between.
 * All are optional, and no more than two should be non-nil. The object
 * type should match the type of the property being animated (using the
 * standard rules described in CALayer.h). The supported modes of
 * animation are:
 *
 * - both `fromValue' and `toValue' non-nil. Interpolates between
 * `fromValue' and `toValue'.
 *
 * - `fromValue' and `byValue' non-nil. Interpolates between
 * `fromValue' and `fromValue' plus `byValue'.
 *
 * - `byValue' and `toValue' non-nil. Interpolates between `toValue'
 * minus `byValue' and `toValue'. */

@property(nullable, strong, nonatomic) id fromValue;
@property(nullable, strong, nonatomic) id toValue;
@property(nullable, strong, nonatomic) id byValue;
@end

可转换性

AXAnimationChain框架还提供了将CABasicAnimation无缝转换为CAKeyframeAnimation的功能:

ConvertSample

动画中,左边是CABasicAnimation,右边是CAKeyframeAnimation,两者对应的动画曲线是一致的。

要使用动画转换,请参考:

#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>
#import "CAMediaTimingFunction+Extends.h"

@interface CAAnimation (Convertable)
@end

@interface CAKeyframeAnimation (Convertable)
+ (instancetype)animationWithBasic:(CABasicAnimation *)basicAnimation;
+ (instancetype)animationWithBasic:(CABasicAnimation *)basicAnimation usingValuesFunction:(double (^)(double t, double b, double c, double d))valuesFunction;
@end

需求

AXAnimationChain 对系统版本支持到iOS8.0,需要使用到的框架:

  • Foundation.framework

  • UIKit.framework

  • QuartzCore.framework

使用的时候最好使用最新版Xcode。

AXAimationChain 添加到您的项目

源文件

或者,您还可以直接将所有源文件添加到您的项目中。

  1. 下载最新的代码版本,或将存储库作为git子模块添加到您的git跟踪项目中。
  2. 在Xcode中打开您的项目,然后将源组拖放到您的项目上(使用“产品导航器视图”)。如果您在项目外提取了代码存档,请确保选择复制项。
  3. 在需要的位置使用#import "AXAimationChain.h"引入AXAnimationChain。
  4. 如果单独使用AXSpringAnimationConvertable以及TimingControl等特性,则只需导入#import "AXCoreAnimation.h"即可。

许可协议

此代码根据MIT许可证的条款和条件分发。

使用

请参考示例工程代码以及API。

不足

此项目在开发时较为庞大,基础的核心类已经构建完成,基本目标已经实现,但仍有很多需要完善的地方。后续会逐步完善并发布Release版本。

声明

转载需注明出处:http://devedbox.com/AXAnimationChain/