Animations開源動效分析(二)POP-Stroke動畫

  1. 本教程源碼Animations 做者 YouXianMing,建議配合源碼項目食用php

  2. Facebook pop動畫框架簡易教程請移步 Facebook Pop 使用指南html

  3. CoreAnimation不簡易教程ios

  4. 若是不想看第三條的教程,也要弄明白CALayer的隱式動畫,不然看本文會疑惑,請移步CALayer的隱式動畫和顯式動畫git

CAMediaTimingFunction

今天咱們來看一下研究一下CAMediaTimingFunction類,它是一個動畫的時間線控制類,他所控制的時間線,能夠是是一條直線、曲線或者折線,以下:github

poster.jpg

這是用一個開源軟件生成的CAMediaTimingFunction,軟件地址是keefo/CATweakerspring

可見,通常自定義的CAMediaTimingFunction經過調用框架

/* Creates a timing function modelled on a cubic Bezier curve. The end
 * points of the curve are at (0,0) and (1,1), the two points 'c1' and
 * 'c2' defined by the class instance are the control points. Thus the
 * points defining the Bezier curve are: '[(0,0), c1, c2, (1,1)]' */

+ (instancetype)functionWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y;

- (instancetype)initWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y;

兩個方法,傳入四個位置點參數生成。 注:上圖中XY軸區間都是[0,1];dom

這個類,在什麼地方用到呢?函數

  1. CALayer的隱式和顯式動畫,CATransactionanimationTimingFunction設置。post

  2. CAKeyframeAnimation有相關設置。

  3. CABasicAnimation是線性的動畫,一條直線。

  4. CASpringAnimation彈簧動畫是也是有一個特殊的走向,屬於CAMediaTimingFunction的特殊封裝。

  5. POP也借用了CAMediaTimingFunction類實現非線性動畫。

下面這個網站能夠在線調試,cubic-bezier,雖然是給CSS工程師用的,可是通用的。
圖片描述

上圖中,藍色的方塊的運動就是線性的,紅色方塊是非線性的。

iOS7開始,iOS系統大量引入了非線性動畫。

0-example-2.gif
0-example-1.gif

上圖引用自 使用 iOS 8 Spring Animation API 建立動畫

Spring動畫

彈簧(Spring)動畫是一種特殊曲線的非線性動畫,由於用的地方太多,因此不管是CoreAnimation仍是POP,都將其進行了封裝CASpringAnimation,POPSpringAnimation

二者有一點區別,參考源碼中的CASpringAnimationPOP-Spring動畫參數詳解
POPSpringAnimation

POP-Stroke動畫

687474703a2f2f696d61676573323031352e636e626c6f67732e636f6d2f626c6f672f3630373534322f3230313531312f3630373534322d32303135313131373131333135333337342d313337303739333939372e676966

今天咱們來分析一下POP-Stroke動畫的源代碼,首先interface中聲明瞭一個CAShapeLayer是中心的圓,timer是一個定時器。這個GCDTimer是做者對GCD進行的一層對象化封裝。

@interface PopStrokeController ()

@property (nonatomic, strong) CAShapeLayer  *circleShape;
@property (nonatomic, strong) GCDTimer      *timer;

@end

實現的思路是,定時改變CAShapeLayer的startStoke和endStoke屬性,改變圓的繪製弧度,使用POP的Spring動畫控制其改變數值。

- (void)setup {
    
    [super setup];
    
    self.circleShape           = [CAShapeLayer layer];
    self.circleShape.strokeEnd = 0.f;
    self.circleShape.lineCap   = kCALineCapRound;
    
    StrokeCircleLayerConfigure *config = [StrokeCircleLayerConfigure new];
    config.lineWidth                   = 4.f;
    config.startAngle                  = 0;
    config.endAngle                    = M_PI * 2;
    config.radius                      = 55.f;
    config.circleCenter                = self.contentView.middlePoint;
    config.strokeColor                 = [UIColor cyanColor];
    [config configCAShapeLayer:self.circleShape];   
    [self.contentView.layer addSublayer:self.circleShape];
    
    _timer = [[GCDTimer alloc] initInQueue:[GCDQueue mainQueue]];

    [_timer event:^{
        
        CGFloat value1 = arc4random() % 101 / 100.f;
        CGFloat value2 = arc4random() % 101 / 100.f;
        
        POPSpringAnimation *strokeAnimationEnd = [POPSpringAnimation animationWithPropertyNamed:kPOPShapeLayerStrokeEnd];
        strokeAnimationEnd.toValue             = @(value1 > value2 ? value1 : value2);
        strokeAnimationEnd.springBounciness    = 12.f;
        
        POPSpringAnimation *strokeAnimationStart = [POPSpringAnimation animationWithPropertyNamed:kPOPShapeLayerStrokeStart];
        strokeAnimationStart.toValue             = @(value1 < value2 ? value1 : value2);
        strokeAnimationStart.springBounciness    = 12.f;
        
        POPBasicAnimation *strokeAnimationColor  = [POPBasicAnimation animationWithPropertyNamed:kPOPShapeLayerStrokeColor];
        strokeAnimationColor.toValue             = (__bridge id)([self randomColor].CGColor);
        
        [self.circleShape pop_addAnimation:strokeAnimationEnd forKey:@"layerStrokeAnimation"];
        [self.circleShape pop_addAnimation:strokeAnimationStart forKey:@"layerStrokeAnimation1"];
        [self.circleShape pop_addAnimation:strokeAnimationColor forKey:@"layerStrokeAnimation2"];
        
    } timeIntervalWithSecs:1];
    
    [_timer start];
}

- (UIColor *)randomColor {

    return [UIColor colorWithRed:arc4random() % 101 / 100.f
                           green:arc4random() % 101 / 100.f
                            blue:arc4random() % 101 / 100.f
                           alpha:1];
}

咱們能夠看到,POP支持了CALayer的全部動畫屬性,上面代碼中用的

NSString * const kPOPShapeLayerStrokeStart = @"shapeLayer.strokeStart";
NSString * const kPOPShapeLayerStrokeEnd = @"shapeLayer.strokeEnd";
NSString * const kPOPShapeLayerStrokeColor = @"shapeLayer.strokeColor";

分別對應CAShapeLayer的繪製顏色,起始比例區間。

/* The color to fill the path's stroked outline, or nil for no stroking.
 * Defaults to nil. Animatable. */

@property(nullable) CGColorRef strokeColor;

/* These values define the subregion of the path used to draw the
 * stroked outline. The values must be in the range [0,1] with zero
 * representing the start of the path and one the end. Values in
 * between zero and one are interpolated linearly along the path
 * length. strokeStart defaults to zero and strokeEnd to one. Both are
 * animatable. */

@property CGFloat strokeStart;
@property CGFloat strokeEnd;

而後經過生成隨機數的方式,用定時器定時改變,同時隨機改變了顏色。因此總共使用了三個Spring動畫。

相同原理的Demo還有Easing-圓環動畫

687474703a2f2f696d61676573323031352e636e626c6f67732e636f6d2f626c6f672f3630373534322f3230313531312f3630373534322d32303135313132343130353630383039332d3936373031303436332e676966

只是這例子中用了做者本身封裝的YXEasing類。

總結

非線性動畫對於要精益求精交互工程師來講,是一把劍利的刃。放在iOS5時代可能由於設備性能等問題,仍是把雙刃劍,但如今來講,已經徹底是提高APP動效交互的利器了。

相關閱讀: 緩動函數速查表

相關文章
相關標籤/搜索