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

版本记录

版本号 时间
V1.0 2017.07.23

前言

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

BarrageRenderer文件

下面看一下这个头文件。

#import 

#import "BarrageHeader.h"

@class BarrageDescriptor;
@class BarrageRenderer;

@protocol BarrageRendererDelegate 

@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 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 

@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 

@interface JJBarrageRendererVC : UIViewController

@end


3. JJBarrageRendererVC.m

#import "JJBarrageRendererVC.h"
#import "BarrageRenderer.h"
#import "JJBarrageModel.h"

@interface JJBarrageRendererVC () 

@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


功能效果

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

直播中BarrageRenderer弹幕的显示(二)—— 工程实践_第1张图片
功能效果1
直播中BarrageRenderer弹幕的显示(二)—— 工程实践_第2张图片
功能效果2

后记

未完,待续~~~

直播中BarrageRenderer弹幕的显示(二)—— 工程实践_第3张图片

你可能感兴趣的:(直播中BarrageRenderer弹幕的显示(二)—— 工程实践)