該篇主要為大家講解兩個用起來比較簡單,但是效果卻極好的strokeEnd和strokeStart。本文通過兩個項目來對它們的使用進(jìn)行演示。
strokeEnd以及strokeStart值的范圍均為0-1,表示一段路徑的結(jié)束點和起始點。對于這兩個屬性的解釋就是這么多。蘋果的開發(fā)文檔也是寥寥數(shù)語。那它們能實現(xiàn)什么樣的效果呢。請看效果圖。
strokeEnd && strokeStart項目:

該gif展示的是一個類似于回形針?biāo)频膭赢?。結(jié)合筆者前兩篇文章的CAShapeLayer、UIBezierPath以及CABasicAnimation的相關(guān)知識應(yīng)該會較為容易地分析出該動畫的實現(xiàn)原理。
- 項目動畫原理簡要分析
在前文我們已經(jīng)道出了實現(xiàn)該項目需要的大致知識點。通過UIBezierPath以及CAShapeLayer去繪制對應(yīng)的線行圖形,并結(jié)合CABasicAnimation去實現(xiàn)相關(guān)動畫(如果對這些技術(shù)不是很熟悉可以詳讀筆者的前兩篇文章Core Animation:CAKeyframeAnimation && mask]和iOS轉(zhuǎn)場動畫(Push))。
在這些技術(shù)的支撐下我們便可以很快地完成回形針的繪制了。
1.為了項目的美觀,我們對控制器做一些小小的裝飾,將背景顏色改為橙色。并在控制器中拖拽一個UIView,添加約束、切割圓角。在這里教大家一個在storyboard中切割圓角的一個小方法(已經(jīng)清楚的可自行忽略)。-
storyboard設(shè)置圓角
打開storyboard選擇剛添加上的UIView,將目光移到屬性面板界面,具體位置如下圖:
-
2.使用UIBezierPath和CAShapeLayer繪制回形針圖形
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(90, 90)];
[path addLineToPoint:CGPointMake(90, 40)];
[path addArcWithCenter:CGPointMake(65, 40) radius:25 startAngle:0 endAngle:M_PI clockwise:NO];
[path addLineToPoint:CGPointMake(40, 90)];
[path addArcWithCenter:CGPointMake(55, 90) radius:15 startAngle:M_PI endAngle:0 clockwise:NO];
[path addLineToPoint:CGPointMake(70, 50)];
[path addArcWithCenter:CGPointMake(62, 50) radius:8 startAngle:0 endAngle:M_PI clockwise:NO];
[path addLineToPoint:CGPointMake(54, 120)];
_layer = [CAShapeLayer layer];
_layer.path = path.CGPath;
_layer.lineWidth = 5.0f;
_layer.lineCap = kCALineCapRound;
_layer.lineJoin = kCALineJoinRound;
_layer.fillColor = [UIColor clearColor].CGColor;
_layer.strokeColor = [UIColor greenColor].CGColor;
[self.whiteView.layer addSublayer:_layer];
3.為圖層添加動畫并設(shè)置KeyPath為strokeEnd
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animation.fromValue = @(0.0f);
animation.toValue = @(1.0f);
animation.duration = 1.5f;
[_layer addAnimation:animation forKey:@"animationStrokeEnd"];
此時運行應(yīng)用,回形針圖形緩慢的繪制的動畫已經(jīng)展現(xiàn)出來了。那么我們?nèi)绾巫尰匦吾樤诶L制到一定時間的時候讓已經(jīng)繪制完的回形針慢慢消失呢?這個時候便用到了strokeStart。
4.遵循代理,實現(xiàn)代理方法
animation.delegate = self;
我們在以下的兩個代理方法中去做一些操作來實現(xiàn)動畫效果。
- (void)animationDidStart:(CAAnimation *)anim;
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
憑借代理方法的字面意思我們也可以比較清楚第一個代理方法在動畫開始時會被調(diào)用,第二個代理方法則是在動畫結(jié)束時會被調(diào)用。那我們在start的代理方法中對layer做KeyPath為strokeStart的動畫會有什么效果?
- (void)animationDidStart:(CAAnimation *)anim {
// 判斷動畫的類型
if ([anim isEqual:[_layer animationForKey:@"animationStrokeEnd"]]) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
CABasicAnimation *animationStart = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
animationStart.fromValue = @(0.0f);
animationStart.toValue = @(1.0f);
animationStart.duration = 1.5f;
animationStart.delegate = self;
// 設(shè)置動畫結(jié)束時保持最終狀態(tài)
animationStart.fillMode = kCAFillModeForwards;
animationStart.removedOnCompletion = NO;
[_layer addAnimation:animationStart forKey:@"animationStrokeStart"];
});
}
}
運行應(yīng)用,該項目就基本完成了。為了完美,我們在動畫結(jié)束后移除了相關(guān)的動畫和layer,并限制動畫正在進(jìn)行中時點擊繪制按鈕不進(jìn)行相關(guān)動作。
詳細(xì)代碼見GitHub
https://github.com/RookieAngry/Demo_ClipAnimation
在這里再分享一個項目,同樣還是先看效果圖:

這是一個下載按鈕帶進(jìn)度條的項目。這個項目算是筆者前面兩篇文章以及strokeEnd的一個綜合項目。該項目的實現(xiàn)并不是很復(fù)雜。我們還是對動畫進(jìn)行拆解,一步一步分析動畫的實現(xiàn)過程。
由于該項目復(fù)雜程度不高,主要是一些技術(shù)的綜合使用,這些技術(shù)在筆者的前面的一些文章中已經(jīng)有所講解,所以在此便不做過多的解釋,用一張圖去分析項目的整個過程,各個環(huán)節(jié)的實現(xiàn)需要用到哪些技術(shù)希望讀者自行進(jìn)行思考。
-
項目實現(xiàn)原理圖解
項目GitHub
https://github.com/Samueler/Demo_ClipAnimation
項目來源于KITTEN大神的《A GUIDE TO IOS ANIMATION》

