测试已测试 | ✗ |
语言语言 | SwiftSwift |
许可 | MIT |
发布上次发布 | 2017年4月 |
SwiftSwift 版本 | 3.0 |
SPM支持 SPM | ✗ |
由 devedbox 维护。
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();
看起来比较冗余,但仔细阅读会发现,其实只有 一行代码。
链接和组合在协议 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 animator
发送 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
结构: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];
}
}
AXAnimationChain
就是通过这样的关系把所有 链接 和 组合 的 animator
管理起来的,在完成关系的链接或组合之后,需要向最后一个 animator
发送 -start
消息动画才能正常进行。animator
在接收到 -start
消息后,会逐级遍历 superAnimator
直至 superAnimator.superAnimator==nil
,此时获取到 superSuperAnimator
,从 superSuperAnimator
自祖先往下逐级进行动画,组合 的动画会 同时 进行,链接 的动画则按 顺序 进行。
时间曲线,时间曲线用于描述动画随时间进行的速度。除了包含系统默认的时间曲线之外,AXAnimationChain
还提供了以下曲线以呈现更漂亮的动画:
自 iOS2.0
起就为 iOS 平台提供了 CoreAnimation 的支持,但在 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来进行开发。
AXAnimationChain
添加到您的项目中您还可以直接将这些源文件添加到您的项目中。
AXAnimationChain
时,请使用#import "AXAimationChain.h"
。AXSpringAnimation
或者Convertable
以及TimingControl
等特性,只需导入#import "AXCoreAnimation.h"
即可。此代码遵循MIT许可证的条款和条件。MIT许可证
请参考示例工程代码和API。
这个项目在开发时相当庞大,已经构建好了基本的核心类,基本目标已经实现,但还有许多需要完善的地方,后面会逐步完善并发布Release版本。
转载需要注明出处:http://devedbox.com/AXAnimationChain/