閒來無事,狂進了materialup網站,不經意間瞅見一個下載的小動畫,覺得很是有趣.於是,我就它給實現一下~
設計靈感
設計此效果的作者 Nick;
開始之前你需要了解的
圖上只是一些類的常用屬性,後邊更多程式碼會講到.
怎樣分解動畫
關於分解gif,其實用mac 預覽 開發gif檔案,就可以看到所有幀的圖片.
考慮到適配問題service類裡已經提取好了.
怎樣連貫動畫
連貫動畫是展示你做的效果流暢不流暢,看著舒服不舒服的能力.其實我是也是嘗試很多遍,讓很多人看了這個效果,有說彆扭的我們就改,咋順咋來.所以讓動畫連貫起來尤為重要.
第一,就是要動畫節點要選準確,定位好動畫與動畫的銜接處.
第二,讓動畫結束時,恢復自然狀態,而不是預設狀態.儘量不要有太大的差異和不規整的地方
第三,使用組合動畫,掐好時間節點.
簡單的就說就說這麼多,下面我們開始演練程式碼~~
程式碼實現
基本實現想法
1.自定義UIControl類,因為它本身就是UIView子類,做點選事件的View再好不過.(另一種方式用block點選回撥)
2.點選區域是否在圓內判斷
3.兩個CAShapeLayer圓環+(一個CAShapeLayer箭頭和CAShapeLayer豎線)組合成箭頭+label
4.一個service類管理建立所用到的path和animation
service 類
service屬性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@property (nonatomic , assign) CGRect viewRect; @property (nonatomic, strong) UIBezierPath *progressPath; /** 關鍵幀 **/ @property (nonatomic, strong) UIBezierPath *arrowStartPath; @property (nonatomic, strong) UIBezierPath *arrowDownPath; @property (nonatomic, strong) UIBezierPath *arrowMidtPath; @property (nonatomic, strong) UIBezierPath *arrowEndPath; @property (nonatomic, strong) UIBezierPath *arrowWavePath; @property (nonatomic, strong) UIBezierPath *verticalLineStartPath; @property (nonatomic, strong) UIBezierPath *verticalLineEndPath; @property (nonatomic, strong) UIBezierPath *succesPath; |
service方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
/** * 線到點動畫 * * @param values 關鍵幀 * * @return 動畫組 */ - (CAAnimationGroup *)getLineToPointUpAnimationWithValues:(NSArray *)values; /** * 箭頭到線的動畫 * * @param values 關鍵幀 * * @return 動畫組 */ - (CAAnimationGroup *)getArrowToLineAnimationWithValues:(NSArray *)values; /** * 獲取圓圈進度 * * @param progress 當前進度值 * * @return path */ - (UIBezierPath *)getCirclePathWithProgress:(CGFloat)progress; /** * 繪製波浪線 * * @param offset 偏移量 * @param height 浪高 * @param curvature 浪曲 * * @return path */ - (UIBezierPath *)getWavePathWithOffset:(CGFloat)offset WaveHeight:(CGFloat)height WaveCurvature:(CGFloat)curvature; /** * 是否顯示進度label * * @param isShow YES/NO * * @return 彈性動畫 */ - (CASpringAnimation *)getProgressAnimationShow:(BOOL)isShow; /** * 線變成功動畫 * * @param values 關鍵幀 * * @return 動畫組 */ - (CAAnimationGroup *)getLineToSuccessAnimationWithValues:(NSArray *)values; /** * 獲取進度label Rect * * @return Rect */ - (CGRect)getProgressRect; |
service key
1 2 3 4 5 6 7 8 9 |
/* animation key */ static NSString * kLineToPointUpAnimationKey = @"kLineToPointUpAnimationKey"; static NSString * kArrowToLineAnimationKey = @"kArrowToLineAnimationKey"; static NSString * kProgressAnimationKey = @"kProgressAnimationKey"; static NSString * kSuccessAnimationKey = @"kSuccessAnimationKey"; |
service 比例係數
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
//箭頭比例 static const double arrowHScale = 130.00/250.00; //箭頭頭部高比例 static const double arrowTWScale = 96.00/250.00; static const double arrowTHScale = 50.00/250.00; // static const double lineWScale = 176.00/250.00; static const double pointSpacingScale = 16.00/250.00; static const double successPoint1ScaleX = 90.00/250.00; static const double successPoint1ScaleY = 126.00/250.00; static const double successPoint2ScaleX = 120.00/250.00; static const double successPoint2ScaleY = 160.00/250.00; static const double successPoint3ScaleX = 177.00/250.00; static const double successPoint3ScaleY = 95.00/250.00; static const NSInteger kSpacing = 2; |
download 類
屬性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/** * 進度:0~1 */ @property (nonatomic, assign) CGFloat progress; /** * 進度寬 */ @property (nonatomic, assign) CGFloat progressWidth; /** * 停止動畫 */ - (void)stopAllAnimations; /** * block 形式點選回撥 */ //@property (nonatomic, strong) void (^ didClickBlock)(); |
所有方法預覽
方法比較多,在這不一一展示了,有感興趣的童鞋可以直接去github下載,記得點個星星哦~~~?
呼叫
新增事件
1 |
[downloadView addTarget:self action:@selector(updateProgress) forControlEvents:UIControlEventTouchUpInside]; |
或者block回撥
1 2 3 4 |
// downloadView.didClickBlock = ^{ // // _timer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(timeDown) userInfo:nil repeats:YES]; // }; |
這裡模擬網路請求資料
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// 模擬網路請求資料進度 - (void)timeDown{ _timeCount -= 1; _progress += 0.005; self.downloadView.progress = _progress; if (_timeCount <= 0) { [self initData]; [_timer invalidate]; _timer = nil; } } |
最終效果
現實與理想還是有些差距,希望不是很大,在此分享一下自己研究的經驗,有任何問題都可以Issues我,