最近在研究直播的相關知識,在網上看到了不少優秀的開源項目,但都沒有看到映客那個刷禮物的效果,於是手癢癢,決定自己做一個。
1. 首先從簡單的開始,文字描邊+連擊效果,這個比較簡單,只要重寫 UILabel 的
- (void)drawTextInRect:(CGRect)rect
就可以達到文字描邊的效果;然後開定時器,讓數字增加,動畫效果用關鍵幀動畫控制。
2. 然後仿照映客的 UI 自定義 View ,控制動畫,從屏幕外面進入,然後顯示連擊效果,最後隱藏,恢復到初始位置。
3. 上面的動畫效果只要稍微有點動畫基礎,很容易就搞定了。做到這裡我冷靜下來,不再往下面做了,因為事情遠遠沒有想象的那麼簡單。首先考慮的是,在收到禮物消息的回調時去賦值數據源,運行動畫,但是這個回調是是一個字典數組,裡面包含了一段時間內多條消息,他們是有順序的,這是其一;其二,這個回調調用次數會很頻繁,短時間內就會收到更多的消息數組。所以需要把這些消息處理成隊列,然後播放動畫效果,一個動畫效果播放完成後,再從消息隊列中取下一個消息,繼續播放下一個動畫,這樣才能保證動畫的播放順序不回亂。
說到隊列的話就想到了多線程,NSOperation ,我們可以重寫它,然後在 start 方法中添加動畫,但是注意我們只是需要讓這些消息排隊,更新 UI 還是要在主線程操作;我們還要手動觸發 NSOperation 的 KVO,告訴這個操作什麼時候開始,什麼時候算是結束,我們想在一個動畫播放完畢後再執行下一個動畫,於是我這裡定義了一個 block ,在動畫結束時,傳遞給 NSOperation ,告訴它動畫結束了。
@synthesize finished = _finished; @synthesize executing = _executing; - (instancetype)init { self = [super init]; if (self) { _executing = NO; _finished = NO; } return self; } - (void)start { if ([self isCancelled]) { self.finished = YES; return; } self.executing = YES; [[NSOperationQueue mainQueue] addOperationWithBlock:^{ _presentView = [[PresentView alloc] init]; _presentView.model = _model; // i % 2 控制最多允許出現幾行 _presentView.frame = CGRectMake(-self.listView.frame.size.width / 2, 300 - (_index % 2) * 70, self.listView.frame.size.width / 2, 40); _presentView.originFrame = _presentView.frame; [self.listView addSubview:_presentView]; [self.presentView animateWithCompleteBlock:^(BOOL finished) { self.finished = finished; }]; }]; } #pragma mark - 手動觸發 KVO - (void)setExecuting:(BOOL)executing { [self willChangeValueForKey:@"isExecuting"]; _executing = executing; [self didChangeValueForKey:@"isExecuting"]; } - (void)setFinished:(BOOL)finished { [self willChangeValueForKey:@"isFinished"]; _finished = finished; [self didChangeValueForKey:@"isFinished"]; }
注意這裡 :
_presentView.frame = CGRectMake(-self.listView.frame.size.width / 2, 300 - (_index % 2) * 70, self.listView.frame.size.width / 2, 40);// i % 2 控制最多允許出現幾行 queue.maxConcurrentOperationCount = 2; // 隊列分發
當時其實只是實現了一個隊列,按順序一個一個播放,如何實現 N 列並發呢?其實把這些並發的動畫隊列想象成圖片的多並發異步下載就好了,下意識地就加了上面兩句控制並發列數的代碼。能這麼順利做出來,是因為最近仔細研究了 SDWebImage 的源碼,不覺得重寫 NSOperation 那個方式很熟悉麼~哈哈。最近工作忙,動畫的細節和封裝性沒有再完善,不過易用性我感覺還是很好的,最後附上 demo 地址和使用方法,祝大家玩得開心~
Demo 地址:https://github.com/cooxu/PresentAnimView.git