iOS開源:AXAnimationChain - 鏈式動畫庫

skybix 7年前發布 | 13K 次閱讀 Spring iOS開發 移動開發

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();
    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

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 , 表示此 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 自祖先往下逐級進行動畫, 組合 的動畫會 同時 進行, 鏈接 的動畫則按 順序 進行.

Features

輕量級解決方案

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

一行代碼搞定復雜的動畫管理,提高代碼維護效

TimingControl

時間曲線,時間曲線用于描述動畫隨時間進行的速度, AXAnimationChain 除了包含系統默認的時間曲線之外,還提供了如下的曲線以呈現更漂亮的動畫:

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 相通用:

動畫中,左邊正方形使用的是 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

CocoaPods is the recommended way to add AXWebViewController to your project.

  1. Add a pod entry for AXPopoverView to your Podfile pod 'AXAimationChain', '~> 0.1.0'
  2. Install the pod(s) by running pod install .
  3. Include AXPopoverView wherever you need it with #import "AXAimationChain.h" .
  4. 若需要單獨使用 AXSpringAnimation 或者 Convertable 以及 TimingControl 等特性的話,只需要將podfile里邊 AXAnimationChain 替換為 AXAnimationChain/CoreAnimation 即可,即: pod 'AXAimationChain/CoreAnimation', '~> 0.1.0' .

Source files

Alternatively you can directly add all the source files to your project.

  1. 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 AXPopoverView wherever you need it with #import "AXAimationChain.h" .

License

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

使用

請參考示例工程代碼以及API.

不足

此項目在開展的時候比較龐大,基礎的核心類已經構建好了,基本目標已經達成,但是還有很多需要完善的地方,后邊會逐步完善并發布Release版本.

 

 

 本文由用戶 skybix 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!