BarrageKit弹幕插件

BarrageKit弹幕插件


前言


现在直播这么火,好多直播框架,诸如IJKMediaFramework等更是方便了直播类APP的开发,那我们也一起给它添砖加瓦吧。

插件介绍


插件是基于Objective-C编写的,整体思路较为简单,功能包括:

  1. 弹幕的滚动方向、滚动速度
  2. 弹幕的暂停与恢复、显示与隐藏
  3. 弹幕的类型:纯文字弹幕、投票类弹幕、其他等(可自定义)
  4. 弹幕的推送方式:主动获取弹幕源、被动接收
  5. 弹幕的缓存,避免大量弹幕出现时内存Boom

还有一些不完善的地方(比如弹幕的轨道现为随机生成,可能会重叠)及一些新的功能欢迎issue

插件展示


  • 四个方向的弹幕滚动
四个方向的弹幕滚动
  • 弹幕的暂停与恢复


    弹幕的暂停与恢复

核心代码介绍


BarrageManager弹幕管理者

数组介绍:

  • _cachePool为弹幕单元的缓冲数组,从屏幕上移除的BarrageScene会加入到该数组中
  • _barrageScene为当前屏幕上正在显示的弹幕显示单元的数组,弹幕显示的时候会加入到该数组中

BarrageManager 作为弹幕的管理者,流程为:

  • 初始化弹幕manager,启动timer,主动拉取弹幕数据,调用-delegate barrageManagerDataSource返回数据。
  • 调用- (void)showWithData:(id)data方法显示弹幕,data可以为BarrageModelNSArray格式
    • 判断缓冲池是否为空,为空则新建弹幕显示单元BarrageScene,并加入到_barrageScene数组中。若不为空,则取出_cachePoolfirstObject进行重用并从_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加入到managercachePool中等待被重用

  • 重用

  • 弹幕从BarrageManagercachePool中取出来,根据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:

  • ①如果弹幕为投票类型的弹幕时,请重写ViewControllertouchesBegan 方法
- (void)touchesBegan:(NSSet<UITouch *> *)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);
        }
    }];
}
  • ②重写ViewControllerdealloc方法,执行BarrageManagertoDealloc
  • ③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中的初始化代码

最后

大家查看项目后,欢迎issue,同时有其他的功能或建议欢迎提出来,简书、github均可。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容