美文网首页iOS Collectionlive动画
iOS-FXDanmaku弹幕库介绍、相关技术分享

iOS-FXDanmaku弹幕库介绍、相关技术分享

作者: ShawnFoo | 来源:发表于2017-02-26 21:31 被阅读802次

前言

去年, 2016年, 一大波直播平台在移动端涌出, 直播慢慢步入了人们的视角. 网上如今能够看到各式各样的直播, 如秀场直播、游戏直播、体育直播、娱乐直播等等.

在各种类型的直播中, 弹幕在PC、移动端都几乎成为了标配, 今天在这里主要介绍一下个人开源的iOS弹幕, 以及提前为实现一款弹幕库涉及的相关技术分享的相关篇章占坑, 虽不细至于手把手教如何实现, 但关键点都会有所涉及且不仅限于实现弹幕, 如iOS中用pthread实现生产者消费者模型、响应正在执行动画对象的点击事件、实现某类对象复用的ReuseQueue、使用GCD封装实现可取消未执行代码块的OperationQueue等等, 对这些更感兴趣的朋友麻烦直接滑至最后一段.

欢迎各位大神指点一二.

广告

统计了各渠道的一周浏览记录, 以及github浏览次数、评论留言数, 感觉弹幕估计是有点过时了..感兴趣的朋友比较少, 所以弹幕相关技术分享打算暂时一缓. 准备开源并分享一下可能更多人感兴趣的序列帧动画引擎, Demo会通过分别Core Animation以及个人FXAnimationEngine来实现花椒礼物动画的效果(资源花椒ipa中提取), 比较内存占用, 动画被系统打断情况下的表现, 图片解码相关知识等. 此外, 还会分享一下礼物资源热更的方案.

Github

Talk is cheap, I'll show you the code.
请大力点击上方超链接⬆️⬆️⬆️⬆️⬆️ (git clone 9mb+)

若翻墙下载速度不佳, 可至百度网盘地址下载 1.0.2 Release版 (400kb+, 无git信息)

特性

  1. 除了UI操作, 其他操作都以代码块交给异步队列处理了.(使用GCD提交的代码块, 最终会由XNU kernel根据CPU使用情况创建新的线程去执行或分配给其他线程执行)
  2. 遵循 生产者消费者模式, 通过pthread去阻塞队列而非使用timer或异步队列开启runloop空转
  3. 定义了包含 弹幕块点击、将出现、已消失事件的delegate
  4. 提供 注册复用 自定义弹幕块 的方法
  5. 各种自定义参数, 如弹幕块移速, 弹幕库插入方向(从上, 从下, 随机), 弹幕库移动方向(左到右, 右到左), 重置弹道位移百分比系数(防前后弹幕块碰撞)、弹幕队列容量控制
  6. 简单易用, 控制方法就三个 start(同时也是恢复), pause, stop. 另外大部分方法都是线程安全的
  7. 轻易适配设备方向旋转
  8. 设置单行配置即可作为 跑马灯、直播间公告 使用

预览图


示例

弹幕设置

// Configuration
FXDanmakuConfiguration *config = [FXDanmakuConfiguration defaultConfiguration];
config.rowHeight = [DemoDanmakuItem itemHeight];
config.dataQueueCapacity = 500;
config.itemMinVelocity = 80;  // set random velocity between 80 and 120 pt/s
config.itemMaxVelocity = 120;
self.danmaku.configuration = config;

// Delegate
self.danmaku.delegate = self;

// Reuse
[self.danmaku registerNib:[UINib nibWithNibName:NSStringFromClass([DemoDanmakuItem class]) bundle:nil]
   forItemReuseIdentifier:[DemoDanmakuItem reuseIdentifier]];
[self.danmaku registerClass:[DemoBulletinItem class] 
     forItemReuseIdentifier:[DemoBulletinItem reuseIdentifier]];

数据添加

// add data for danmaku view to present
DemoDanmakuItemData *data = [DemoDanmakuItemData data];
[self.danmaku addData:data];

// start running
if (!self.danmaku.isRunning) {
    [self.danmaku start];
}

代理事件

- (void)danmaku:(FXDanmaku *)danmaku didClickItem:(FXDanmakuItem *)item withData:(DemoDanmakuItemData *)data {
    // 此处 处理点击
}

- (void)danmaku:(FXDanmaku *)danmaku willDisplayItem:(FXDanmakuItem *)item withData:(FXDanmakuItemData *)data {
    // 此处 处理弹幕块将要出现/展示
}

- (void)danmaku:(FXDanmaku *)danmaku didEndDisplayingItem:(FXDanmakuItem *)item withData:(FXDanmakuItemData *)data {
    // 此处 处理弹幕块完全离开视线,结束展示
}

更多详情 麻烦参照 Gitbub Demo project FXDanmakuDemo.xcworkspace.

有关弹幕库使用问题答疑

1. rowHeight、estimatedRowSpace and rowSpace 三者之间的关系

2. 如何使用nib创建自定义弹幕块


3. 如何适配设备屏幕旋转

如果你的弹幕View 在横竖屏状态下 高度不一样, 比如竖屏高200pt, 横屏约束却是100pt, 那么需要在对应的controller.m文件中加入以下代码(否则 当你的弹幕块使用AutoLayout进行布局时, 横竖屏切换后, 由于视图的frame会变化多次,导致正在展示的弹幕块 出现布局约束冲突的报错)

iOS8+

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
    [self.danmaku pause];
    [self.danmaku cleanScreen];
    
    [coordinator animateAlongsideTransition:nil
                                 completion:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
                                     // resume danmaku after orientation did change
                                     [self.danmaku start];
                                 }];
}

系统版本小于iOS8

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [self.danmaku pause];
    [self.danmaku cleanScreen];
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    [self.danmaku start];
}

安装

Cocoapods(iOS7+)

  1. Podfile中 视情况对应添加以下内容
    platform :ios, 'xxx'
    target 'xxx' do
      pod 'FXDanmaku'
    end
    
  2. pod install

Manually(iOS7+)

直接拖动 FXDanmaku 文件夹 到你的项目 对应结构下

介绍结尾

欢迎各位 提出宝贵的issues, 更多功能建议, 或者改进之处等等. 同时若各位想要了解弹幕库具体实现的其他相关点, 也可在评论区留言.

实现一款弹幕库涉及的相关技术分享(占坑)

以下篇章还未开写, 仅提前占坑..未完待续..
iOS中用pthread实现生产者消费者模型
响应正在执行动画对象的点击事件
实现某类对象复用的ReuseQueue
使用GCD封装实现可取消未执行代码块的OperationQueue

相关文章

网友评论

  • a梦里青草香:楼主你好,请问我用的defaultConfiguration这中配置,在收到消息的时候添加数据发弹幕,发了几个或者几十个之后就不显示了,看了下也不是 config.dataQueueCapacity = 666;这个属性的问题,还有别的地方有限制吗
    ShawnFoo:有代码吗?添加数据在主线程进行的?是不是下发消息太多堵塞主线程了?有没有试过异步连续队列添加数据?
    a梦里青草香:弹幕在做动画的时候有闪烁的感觉,楼主有办法解决吗
    a梦里青草香:我是用defaultConfiguration模式,用一个item的高度做的单行显示
  • d4de4177e332:swift怎么使用该项目
    ShawnFoo:请参考 Using Swift with Cocoa and Objective-C (Swift 4.0.3)

    https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html
  • 谢谢生活:数据是有的,就是看不到试图,reveal还没有测试,我加了一个timer,每5秒当一个进去就可以,不加timer就只显示第一个,dome没有问题,我的也只是集成你的裤,然而不行:sleepy::sleepy::sleepy:
    谢谢生活:@ShawnFoo 可以把你QQ,私信给我吗,UI测试没有生成视图,只有第一个可以生成,代码-(void)addBarrageDArrayOfEmoDanmakuItemData:(NSArray*)Array{
    static NSInteger index = 0;
    for (PushMessage *pushMessage in Array) {
    DemoDanmakuItemData *data = [DemoDanmakuItemData data];
    data.avatarName = [NSString getImageUrlString:pushMessage.avatar].absoluteString;
    data.desc = pushMessage.message;
    [self.danmaku addData:data];
    index++;
    }
    LOG(@"当前是第======%ld=====个弹幕",(long)index);
    if (!self.danmaku.isRunning) {
    [self.danmaku start];
    }
    }

    FXDanmakuConfiguration *config = [FXDanmakuConfiguration defaultConfiguration];
    config.rowHeight = [DemoDanmakuItem itemHeight];
    config.estimatedRowSpace = -10;
    self.danmaku.configuration = config;
    self.danmaku.backgroundColor = [UIColor clearColor];
    self.danmaku.delegate = self;
    config.itemMinVelocity = 80; // set random velocity between 80 and 120 pt/s
    config.itemMaxVelocity = 120;
    [self.danmaku registerNib:[UINib nibWithNibName:NSStringFromClass([DemoDanmakuItem class]) bundle:nil]
    forItemReuseIdentifier:[DemoDanmakuItem reuseIdentifier]];
    谢谢生活:@ShawnFoo 我扣扣是524510161.等下界面测试,看看后面有没有生成试图
    ShawnFoo:Demo我测试过"一次性添加n个数据再开始跑"以及"异步线程定时添加数据"这两种情况都正常. 仅通过目前的描述, 我暂时没想到哪里出问题. 不排除多线程导致的执行顺序与预想逻辑不一致的问题.
    方便的话可以私信发下相关代码, 当然去除敏感部分的, 相关文件即可
  • 谢谢生活: for (PushMessage *pushMessage in Array) {
    DemoDanmakuItemData *data = [DemoDanmakuItemData data];
    data.avatarName = [NSString getImageUrlString:pushMessage.avatar].absoluteString;
    data.desc = pushMessage.message;
    [self.danmaku addData:data];
    index++;
    }
    if (!self.danmaku.isRunning) {
    [self.danmaku start];
    }
    大神我用这个方法,只有第一个弹幕出现了的 其他都没有显示 怎么回事啊
    ShawnFoo:因为你只贴出了部分代码,所以我个人建议通过以下方式来Debug:
    1. 数据源有没有问题? Array数组中的对象个数? 最后遍历时尝试打印一下PushMessage的各个属性值,如果avatar和message为nil或空字符串,那么求出来的弹幕块长度为0,所以看不到
    2. 通过图层分析, 是否创建了对应的弹幕块,可以使用Xcode自带的"Debug View Hierarchy" 或者 选择我已经配置好的 "FXDanmakuDemo_Reveal" scheme来运行Demo配置Reveal进行图层分析(确保本机安装了1.6.x版本的Reveal)

本文标题:iOS-FXDanmaku弹幕库介绍、相关技术分享

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