AXAnimationChain是一个 链式动画库 ,可以用来轻松的创建基于 CAAnimation 的链式动画。 链 的组合方式有两种,一种是 组合 ,另一种则是 链接 ,通过以上两种方式创建的动画,既可以同时进行,也可以按时间先后进行,可以使用较少的代码创建出丰富复杂的动画效果:
简单使用:
_transitionView.spring.centerBy(CGPointMake(0, 100)).easeOut.spring.sizeBy(CGSizeMake(100, 100)).spring.cornerRadiusBy(4).animate();
高级使用(比较冗余):
_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();
self.view.spring.backgroundColorTo([UIColor colorWithRed:1.000 green:0.988 blue:0.922 alpha:1.00]).animate();
看起来比较冗余,但是细读会发现,其实就只有 一行代码 .
链接和 组合 在协议 AXAnimatorChainDelegate 中进行定义,分别是: nextTo: 和 combineWith: ,在使用的过程中应当予以区分.
AXAnimationChain 基于 CoreAnimation 定义了几种 Animator , AXChainAnimator 是基类,预定义了一系列 Animate 操作,可以 链接 、 组合 并且控制动画完成的 回调 :
AXChainAnimator
--AXBasicChainAnimator ==CABasicAnimation
--AXSpringChainAnimator ==CASpringAnimation
--AXKeyframeChainAnimator ==CAKeyframeAnimation
--AXTransitionChainAnimator==CATransitionAnimation
通过链接的方式处理两个 animator , 被链接 的 animator 将会在前者动画(包含 组合 的动画)完成之后进行动画, 大概的示例如下:
[former nextTo:nexter];
Next-To 方法的原型如下:
- (instancetype)nextTo:(id<AXAnimatorChainDelegate>)animator;
当向 former aniamtor 发送 nextTo: 消息之后,返回的是 nexter animator 作为下次 链接 或者 组合 操作的对象,因此 AXAnimationChain 定义了几种常用的操作:
/// 链接到Basic动画并且返回链接的Basic动画. - (AXBasicChainAnimator *)nextToBasic; /// 链接到Spring动画并且放回链接的Spring动画. - (AXSpringChainAnimator *)nextToSpring; /// 链接到Keyframe动画并且放回链接的Keyframe动画. - (AXKeyframeChainAnimator *)nextToKeyframe; /// 链接到Transition动画并且返回链接的Transition动画. - (AXTransitionChainAnimator *)nextToTransition;
在发送消息之后分别返回对应类型的 可操作对象 .
通过组合的方式处理两个 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 , 表示此 animator 为 superAnimator 所链接的 animator , 此时, superAnimator 的 childAnimator 即指向此 animator 作为一个 闭环链 将两者的关系锁定起来; 同样的,某一个 animator 还拥有一个指向 兄弟节点 的 NSArray<AXChainAnimator *> 结构: combinedAnimators 用于管理所组合的 animators ,并且,被组合的 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];
}
}
AXAnimatioChain 就是通过这样的关系把所有 链接 和 组合 的 animator 管理起来的,在完成关系的链接或组合之后,需要向最后一个 animator 发送 -start 消息动画才能正常进行. animator 在接收到 -start 消息之后,会逐级遍历 superAnimator 直至 superAnimator.superAnimator==nil , 此时获取到 superSuperAnimator , 从 superSuperAnimator 自祖先往下逐级进行动画, 组合 的动画会 同时 进行, 链接 的动画则按 顺序 进行.
轻量级解决方案
基于CoreAnimation的封装,安全、高效!
一行代码搞定复杂的动画管理,提高代码维护效
时间曲线,时间曲线用于描述动画随时间进行的速度, AXAnimationChain 除了包含系统默认的时间曲线之外,还提供了如下的曲线以呈现更漂亮的动画:
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 相通用:
动画中,左边正方形使用的是 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 的功能:
动画中,左边是 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
使用的时候最好使用最新版Xcode.
AXAimationChain To Your Project CocoaPods is the recommended way to add AXWebViewController to your project.
pod 'AXAimationChain', '~> 0.1.0' pod install . #import "AXAimationChain.h" . AXSpringAnimation 或者 Convertable 以及 TimingControl 等特性的话,只需要将podfile里边 AXAnimationChain 替换为 AXAnimationChain/CoreAnimation 即可,即: pod 'AXAimationChain/CoreAnimation', '~> 0.1.0' . Alternatively you can directly add all the source files to your project.
#import "AXAimationChain.h" . This code is distributed under the terms and conditions of the MIT license .
请参考示例工程代码以及API.
此项目在开展的时候比较庞大,基础的核心类已经构建好了,基本目标已经达成,但是还有很多需要完善的地方,后边会逐步完善并发布Release版本.
转载需注明出处: http://devedbox.com/AXAnimationChain/