美文网首页OC技术
直播中BarrageRenderer弹幕的显示(二)—— 工程实

直播中BarrageRenderer弹幕的显示(二)—— 工程实

作者: 刀客传奇 | 来源:发表于2017-07-23 14:59 被阅读566次

    版本记录

    版本号 时间
    V1.0 2017.07.23

    前言

    在我们做直播等视频类app的时候,总是有显示和发送弹幕的要求,弹幕可以方便用户进行沟通和互动,增加了娱乐性,增强app等客户端的用户粘度,下面我们就说一下弹幕显示方面的问题和相关框架BarrageRenderer。
    1. 直播中BarrageRenderer弹幕的显示(一)—— 框架介绍
    这一篇就结合工程实现说明该框架的使用。

    BarrageRenderer文件

    下面看一下这个头文件。

    #import <Foundation/Foundation.h>
    
    #import "BarrageHeader.h"
    
    @class BarrageDescriptor;
    @class BarrageRenderer;
    
    @protocol BarrageRendererDelegate <NSObject>
    
    @optional
    
    /// 通过外部渠道获取当前时间,用于内部时间系统; 当依附的视频具有快进快退功能时,必须实现这个函数,并返回时间轴上的当前时刻,即已经播放的时间.
    - (NSTimeInterval)timeForBarrageRenderer:(BarrageRenderer *)renderer;
    
    @end
    
    /// 弹幕渲染器
    @interface BarrageRenderer : NSObject
    
    #pragma mark - life cycle
    
    #pragma mark - control
    
    /// 启动弹幕, 内部时钟从0开始;
    /// 若是stop之后的start,则start函数内部会清空records;
    /// 视频开始的时候需要同时运行此方法.
    - (void)start;
    
    /// 暂停, 已经渲染上去的保持不变, 此时发送弹幕无效, 内部时钟暂停;
    /// 视频暂停的时候需要同时运行此方法.
    - (void)pause;
    
    /// 停止弹幕渲染, 会清空所有; 再发弹幕就无效了; 一切都会停止;
    /// 此方法在不再需要弹幕的时候必须调用,否则可能造成内存泄露.
    - (void)stop;
    
    /// 接收弹幕消息, 如果尚未start, 则调用无效.
    - (void)receive:(BarrageDescriptor *)descriptor;
    
    #pragma mark - config
    
    /// 画布的边距
    @property(nonatomic,assign)UIEdgeInsets canvasMargin;
    
    /// 画布是否拦截事件
    @property(nonatomic,assign)BOOL masked;
    
    /// 调整弹幕整体速度, 需要>0, 否则会被抛弃.
    @property(nonatomic,assign)CGFloat speed;
    
    /// 如果时光倒流, 弹幕能不能重新显示. 若设置为YES, 则当执行后退8s->5s时,会显示6s时刻上的弹幕.
    @property(nonatomic,assign)BOOL redisplay;
    
    /// 获取外部时间的代理,若需将弹幕固定到时间点上,则需设置此代理
    @property(nonatomic,weak)id<BarrageRendererDelegate> delegate;
    
    #pragma mark - output
    
    /// 返回给外部的view
    @property(nonatomic,weak)UIView * view;
    
    /// 获取当前屏幕弹幕数量,spriteName表示弹幕类名,如果传入nil,则计算屏幕显示出的所有弹幕数量.
    - (NSInteger)spritesNumberWithName:(NSString *)spriteName;
    
    /// 逻辑时间,露出参考.
    @property(nonatomic,assign,readonly)NSTimeInterval time;
    
    #pragma mark - z-index
    
    /// 是否开启z-index功能,开启之后,性能会稍有降低,绘图会按照z_index进行,值越大,越靠上;默认关闭.
    @property(nonatomic,assign)BOOL zIndex;
    
    #pragma mark - record
    
    /// 如需要记录,需要在运行start之后立即运行此函数,内部会通过时间差计算delay;
    /// 记录弹幕,可能会序列化到本地; 默认为NO.
    @property(nonatomic,assign)BOOL recording;
    
    /// 加载已经存在的弹幕,如果已经start, 会立刻被调用receive; 否则, 会等到start的时候再调用receive.
    - (void)load:(NSArray *)descriptors;
    
    /// 弹幕记录数组.
    - (NSArray *)records;
    
    @end
    
    

    工程实现

    下面看一下我建立工程的代码。

    1. JJBarrageModel.h
    
    #import <Foundation/Foundation.h>
    
    @interface JJBarrageModel : NSObject
    
    @property (nonatomic, copy) NSString *videoTime;
    @property (nonatomic, copy) NSString *barrageType;
    @property (nonatomic, copy) NSString *fontSize;
    @property (nonatomic, copy) NSString *barrageColor;
    @property (nonatomic, copy) NSString *timestamp;
    @property (nonatomic, copy) NSString *barragePoolId;
    @property (nonatomic, copy) NSString *userHash;
    @property (nonatomic, copy) NSString *barrageID;
    @property (nonatomic, copy) NSString *message;
    @property (nonatomic, assign) NSTimeInterval delay;
    
    @end
    
    
    2. JJBarrageRendererVC.h
    
    
    #import <UIKit/UIKit.h>
    
    @interface JJBarrageRendererVC : UIViewController
    
    @end
    
    
    
    3. JJBarrageRendererVC.m
    
    
    #import "JJBarrageRendererVC.h"
    #import "BarrageRenderer.h"
    #import "JJBarrageModel.h"
    
    @interface JJBarrageRendererVC () <BarrageRendererDelegate>
    
    @property (nonatomic, strong) BarrageRenderer *renderer;
    @property (nonatomic, assign) NSTimeInterval predictedTime;
    @property (nonatomic, strong) NSDate *startDate;
    
    @end
    
    @implementation JJBarrageRendererVC
    
    #pragma mark - Override Base Function
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        self.view.backgroundColor = [UIColor darkGrayColor];
        
        [self setupUI];
        
        //初始化弹幕
        [self initBarrageRenderer];
    }
    
    #pragma mark - Object Private Function
    
    - (void)setupUI
    {
        UIButton *sendButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [sendButton setTitle:@"发送弹幕" forState:UIControlStateNormal];
        sendButton.layer.borderColor = [UIColor yellowColor].CGColor;
        [sendButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
        sendButton.frame = CGRectMake((self.view.center.x - 50), (self.view.center.y - 10), 100, 20);
        [sendButton addTarget:self action:@selector(buttonDidClick) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:sendButton];
    }
    
    //弹幕初始化
    
    - (void)initBarrageRenderer
    {
        self.renderer = [[BarrageRenderer alloc]init];
        self.renderer.view.userInteractionEnabled = NO;
        self.renderer.masked = NO;
        self.renderer.delegate = self;
        self.renderer.redisplay = YES;
        self.renderer.canvasMargin = UIEdgeInsetsMake(30, 0, 30, 0);
        self.predictedTime = 0.0f;
        [self start];
        [self.view addSubview:self.renderer.view];
    }
    
    //开始发送弹幕
    
    - (void)start
    {
        self.startDate = [NSDate date];
        [self.renderer start];
    }
    
    //发送弹幕
    
    - (void)sendBarrageWithModel:(JJBarrageModel *)model
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.renderer receive:[self walkImageTextSpriteDescriptorAWithData:model]];
        });
    }
    
    //加载弹幕描述符
    
    - (BarrageDescriptor *)walkImageTextSpriteDescriptorAWithData:(JJBarrageModel *)model
    {
        BarrageDescriptor * descriptor = [[BarrageDescriptor alloc] init];
        descriptor.spriteName = NSStringFromClass([BarrageWalkTextSprite class]);
        descriptor.params[@"direction"] = @(BarrageWalkDirectionR2L);
        descriptor.params[@"trackNumber"] = @5;
        descriptor.params[@"text"] = model.message?:@"";
        descriptor.params[@"textColor"] = [UIColor whiteColor];
        descriptor.params[@"shadowColor"] = [UIColor darkGrayColor];
        descriptor.params[@"speed"] = @(0.5 * model.message.length + 100);
        return descriptor;
    }
    
    #pragma mark - Action && Notification
    
    - (void)buttonDidClick
    {
        JJBarrageModel *model = [[JJBarrageModel alloc] init];
        model.message = @"我是个弹幕,弹幕,弹幕啊!";
        model.barrageColor = @"ffb412";
        model.fontSize = [NSString stringWithFormat:@"%f", 16.0f];
        model.delay = 0;
        
        [self sendBarrageWithModel:model];
    }
    
    #pragma mark - BarrageRendererDelegate
    
    - (NSTimeInterval)timeForBarrageRenderer:(BarrageRenderer *)renderer
    {
        NSTimeInterval interval = [[NSDate date]timeIntervalSinceDate:self.startDate];
        interval += self.predictedTime;
        return interval;
    }
    
    @end
    
    

    功能效果

    下面我们就看一下功能效果。

    功能效果1 功能效果2

    后记

    未完,待续~~~

    相关文章

      网友评论

        本文标题:直播中BarrageRenderer弹幕的显示(二)—— 工程实

        本文链接:https://www.haomeiwen.com/subject/iwkmkxtx.html