插件是基於Objective-C編寫的,整體思路較為簡單,功能包括:
彈幕的滾動方向、滾動速度
彈幕的暫停與恢復、顯示與隱藏
彈幕的類型:純文字彈幕、投票類彈幕、其他等(可自定義)
彈幕的推送方式:主動獲取彈幕源、被動接收
彈幕的緩存,避免大量彈幕出現時內存Boom
還有一些不完善的地方(比如彈幕的軌道現為隨機生成,可能會重疊)及一些新的功能歡迎issue
四個方向的彈幕滾動
彈幕的暫停與恢復
BarrageManager
彈幕管理者數組介紹:
_cachePool
為彈幕單元的緩沖數組,從屏幕上移除的BarrageScene
會加入到該數組中
_barrageScene
為當前屏幕上正在顯示的彈幕顯示單元的數組,彈幕顯示的時候會加入到該數組中
BarrageManager
作為彈幕的管理者,流程為:
初始化彈幕manager,啟動timer
,主動拉取彈幕數據,調用-delegate barrageManagerDataSource
返回數據。
調用- (void)showWithData:(id)data
方法顯示彈幕,data
可以為BarrageModel
或NSArray
格式
判斷緩沖池是否為空,為空則新建彈幕顯示單元BarrageScene
,並加入到_barrageScene
數組中。若不為空,則取出_cachePool
的firstObject
進行重用並從_cachePool
中移除,添加到_barrageScene
中來
核心代碼如下:
if (_cachePool.count < 1) { // nil BarrageScene *scene = [[BarrageScene alloc] initWithFrame:CGRectZero Model:model]; [_barrageScene addObject:scene]; [_bindingView addSubview:scene]; Weakself; scene.animationDidStopBlock = ^(BarrageScene *scene_){ [weakSelf.cachePool addObject:scene_]; [weakSelf.barrageScene removeObject:scene_]; [scene_ removeFromSuperview]; }; [scene scroll]; }else { //從緩沖池獲取到Scene後,將其從緩沖池中移除 // NSLog(@"get from cache"); BarrageScene *scene = _cachePool.firstObject; [_barrageScene addObject:scene]; [_cachePool removeObjectAtIndex:0]; scene.model = model; [_bindingView addSubview:scene]; [scene scroll]; }
BarrageModel
彈幕模型message
彈幕信息為NSMutableAttributedString
類型,圖片、表情等都可以使用了模型屬性:
//彈幕ID barrage's id @property (assign, nonatomic) NSInteger numberID; //彈幕時間 barrage;s time @property (strong, nonatomic) NSString *time; //彈幕類型 barrage's type @property (assign, nonatomic) BarrageDisplayType barrageType; //彈幕速度 barrage's speed @property (assign, nonatomic) BarrageDisplaySpeedType speed; //彈幕滾動方向 barrage's direction @property (assign, nonatomic) BarrageScrollDirection direction; //彈幕位置 barage's location @property (assign, nonatomic) BarrageDisplayLocationType displayLocation; //彈幕所屬的父View barrage's superView @property (weak, nonatomic) UIView *bindView; //彈幕內容 barrage's content @property (strong, nonatomic, nonnull) NSMutableAttributedString *message; //彈幕作者 barrage's author @property (strong, nonatomic, nullable) id author; //彈幕對象 goal object @property (strong, nonatomic, nullable) id object; //彈幕字體 barrage's textfont @property (copy, nonatomic) UIFont *font; //彈幕字體顏色 barrage's textColor @property (copy, nonatomic) UIColor *textColor;
BarrageScene
彈幕顯示單元滾動Scroll
①根據彈幕的滾動速度和滾動方向計算彈幕的滾動距離和所需要的時間
②使用CABasicAnimation完成動畫,後期彈幕的暫停和回復比較方便
③彈幕滾動完畢後,執行_animationDidStopBlock
,將該scene加入到manager
的cachePool
中等待被重用
重用
彈幕從BarrageManager
的cachePool
中取出來,根據BarrageModel
彈幕信息重新初始化frame且重新開始動畫
暫停 pause
暫停layer動畫即可
CFTimeInterval pausedTime = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil]; self.layer.speed = 0.0; self.layer.timeOffset = pausedTime;
恢復 resume
恢復layer動畫即可
CFTimeInterval pausedTime = [self.layer timeOffset]; self.layer.timeOffset = 0.0; self.layer.beginTime = 0.0; self.layer.speed = 1.0; CFTimeInterval timeSincePause = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime; self.layer.beginTime = timeSincePause;
關閉 close
[self.layer removeAllAnimations]; [self removeFromSuperview];
下載項目導入到項目中,使用時import 'BarrageKit.h'
即可
_manager = [BarrageManager manager]; //出現的View _manager.bindingView = self.view; //delegate _manager.delegate = self; //彈幕顯示位置 _manager.displayLocation = BarrageDisplayLocationTypeDefault; //滾動方向 _manager.scrollDirection = BarrageScrollDirectRightToLeft; //滾動速度 _manager.scrollSpeed = 30; //收到內存警告的處理方式 _manager.memoryMode = BarrageMemoryWarningModeHalf; //刷新時間 _manager.refreshInterval = 1.0; //開始滾動 manager主動獲取彈幕,另外一種方式,`[_manager showBarrageWithDataSource:m]` 退出彈幕即可 [_manager startScroll];
Tips:
①如果彈幕為投票類型的彈幕時,請重寫ViewController
的touchesBegan
方法
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint touchPoint = [touch locationInView:self.view]; [[_manager barrageScenes] enumerateObjectsUsingBlock:^(BarrageScene * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if ([obj.layer.presentationLayer hitTest:touchPoint]) { //彈幕類型為投票類型時,為彈幕添加點擊事件,請在此處添加 /* if barrage's type is ` BarrageDisplayTypeVote `, add your code here*/ NSLog(@"message = %@",obj.model.message.string); } }]; }
②重寫ViewController
的dealloc
方法,執行BarrageManager
的toDealloc
③ViewController收到內存警告時,[_manager didReceiveMemoryWarning];
將會按照memoryMode
指定的方法清楚緩沖池
- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. // 收到內存警告時,清楚彈幕緩沖池 When you receive a memory warning,clean the barrage's cache [_manager didReceiveMemoryWarning]; }
④如果要高度自定義彈幕顯示,可以修改BarrageScene
中的初始化代碼
項目及Demo下載地址