最近在研究直播的相關知識,在網上看到了不少優秀的開源項目,但都沒有看到映客那個刷禮物的效果,於是手癢癢,決定自己做一個。

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