iOS链式动画库、Spring动画,TimingFunction扩展


Summary

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定义了几种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 aniamtor发送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发送以上消息之后,将会分别返回对应类型的可操作对象.

Relationship

AXAnimationChain中,关系的管理采用的是二叉树的理论. 某一个animator对应的类结构中,包含了指向父节点superAnimator用于表示父animator, 表示此animatorsuperAnimator所链接的animator, 此时,superAnimatorchildAnimator即指向此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
自祖先往下逐级进行动画,组合的动画会同时进行,链接的动画则按顺序进行.

Features

  • 轻量级解决方案

  • 基于CoreAnimation的封装,安全、高效!

  • 一行代码搞定复杂的动画管理,提高代码维护效

TimingControl

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

AXSpringAnimation

CoreAnimationiOS2.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
Convertable

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

Requirements

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

  • Foundation.framework

  • UIKit.framework

  • QuartzCore.framework

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

Adding AXAimationChain To Your Project

CocoaPods

  1. CocoaPods is the recommended way to add AXAimationChain to your project.
  2. Add a pod entry for AXAimationChain to your Podfile pod 'AXAimationChain', '~> 0.1.0' Install the pod(s) by running pod install
  3. Include AXAimationChain wherever you need it with #import "AXAimationChain.h"
  4. 若需要单独使用AXSpringAnimation或者Convertable以及TimingControl等特性的话,只需要将podfile里边AXAnimationChain替换为AXAnimationChain/CoreAnimation即可,即:pod 'AXAimationChain/CoreAnimation', '~> 0.1.0'

Source files

  1. Alternatively you can directly add all the source files to your project. Download the latest code version or add the repository as a git submodule to your git-tracked project.
  2. Open your project in Xcode, then drag and drop the source group onto your project (use the "Product Navigator view"). Make sure to select Copy items when asked if you extracted the code archive outside of your project.
  3. Include AXAnimationChain wherever you need it with #import "AXAimationChain.h"
    .4. 如单独使用AXSpringAnimation或者Convertable以及TimingControl等特性,只需要导入#import "AXCoreAnimation.h"
    即可.

License

This code is distributed under the terms and conditions of the MIT license.

使用

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

不足

此项目在开展的时候比较庞大,基础的核心类已经构建好了,基本目标已经达成,但是还有很多需要完善的地方,后边会逐步完善并发布Release版本.

声明

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

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

推荐阅读更多精彩内容