那些H5用到的技术(4)——弹幕

前言
思路
实现
模式
无限循环模式
时间线模式
停止显示弹幕

前言

以前玩卷轴射击游戏的时候,大量的BOSS子弹让我们无路可逃的时候,让我见识到了真正弹幕的威力,可自从A站B站火了之后,大量评论留言参与到了视频的播放中,也让我见识到了“弹幕”的威力,压根视频就没法看了……全看评论去了,就是那么好玩。

现在没有弹幕功能都不好意思说是做视频or直播网站的。而我们也不能落后呐,产品提需求了,活动H5里面弄个弹幕留言,看起来就高大上有木有啊,以前的静态留言形势都太古板啦,弹幕才能用户high起来啊!好吧,本来说这玩意已经比较成熟了,找轮子,结果发现貌似没有html&js版本的,索性就自己写一个吧,暂时满足简单的需求就行。

思路

如下图所示

主要有3个步骤

1、生成弹幕

根据相应的参数,设置弹幕的字体大小,字体颜色,甚至是弹幕背景(VIP功能,类似QQ聊天气泡),总之可以根据需求设计各种不同的弹幕样式。

2、展示弹幕

生成好弹幕我们就要对其进行展示了,目前主流的展示方式有2种,一种是从屏幕的右往左漂移展示,一种是在屏幕的上、中、下进行展示,这里需要考虑到尽量避免弹幕重叠,有效率用屏幕空间,当实在是没有空间了,才考虑重叠。

3、清除弹幕

在设定时间内显示完弹幕,为了节约资源,所以要对其进行移除清理,或者对其进行复用。

实现

话不多说,上代码看注释

  1. /**
  2. * by Leestar54
  3. * 简易弹幕插件 V1.0
  4. */
  5. ;
  6. (function($) {
  7. $.fn.danmu = function(options) {
  8. //默认参数
  9. var defaults = {
  10. fontSize: 16,
  11. color: ‘black‘,
  12. showTime: 10000
  13. }
  14. //使用jQuery.extend 覆盖插件默认参数
  15. var options = $.extend(defaults, options);
  16. var hideTime = defaults.showTime + 500;
  17. //弹幕的行数
  18. var dm_lines = Math.floor($(this).height() / 16);
  19. //当前弹幕行是否有空间进行显示
  20. var dm_line_empty = Array(dm_lines);
  21. for (var i = 0; i < dm_line_empty.length; i++) {
  22. dm_line_empty[i] = true;
  23. }
  24. //中文和英文的宽度要分别算
  25. function getDivWidth(txt, fontSize) {
  26. var len = 0;
  27. var charRatio = fontSize * 5 / 8;
  28. for (var i = 0; i < txt.length; i++) {
  29. if (txt[i].match(/[^\x00-\xff]/ig) != null) //全角中文
  30. len += fontSize;
  31. else
  32. len += charRatio; //非中文经过测试得出比例
  33. }
  34. return len;
  35. }
  36. //公开函数
  37. this.add = function(txt, id, line, color, fontSize) {
  38. if (txt === undefined || txt === ‘‘) {
  39. //抛出异常
  40. throw ‘txt should not be null‘;
  41. }
  42. if (line === undefined || line === ‘‘) {
  43. for (var i = 0; i < dm_line_empty.length; i++) {
  44. if (dm_line_empty[i]) {
  45. dm_line_empty[i] = false;
  46. line = i;
  47. break;
  48. }
  49. }
  50. //如果都满了,就随机覆盖了
  51. if (line === undefined || line === ‘‘) {
  52. line = Math.floor(Math.random() * dm_lines);
  53. }
  54. }
  55. if (color === undefined || color === ‘‘) {
  56. color = defaults.color;
  57. }
  58. if (fontSize === undefined || fontSize === ‘‘) {
  59. fontSize = defaults.fontSize;
  60. }
  61. if (id === undefined || id === ‘‘) {
  62. id = Math.floor(Math.random() * 100000000);
  63. }
  64. //使用dom构造单个弹幕div
  65. var div = document.createElement("div");
  66. div.id = ‘txt_dm‘ + id;
  67. div.innerHTML = txt;
  68. div.style.webkitAnimation = ‘run 1s 8s linear forwards‘;
  69. div.style.position = ‘absolute‘;
  70. div.style.top = line * fontSize + ‘px‘;
  71. div.style.left = $(this).width() + ‘px‘;
  72. //设置宽度,否则字体会自适应换行,影响显示
  73. div.style.width = getDivWidth(txt, fontSize) + ‘px‘;
  74. div.style.fontSize = fontSize + ‘px‘;
  75. div.style.color = color;
  76. $(this).append(div);
  77. $(div).velocity({
  78. translateX: ‘-‘ + ($(this).width() + $(div).width()) + ‘px‘
  79. },
  80. defaults.showTime,
  81. ‘linear‘);
  82. //屏幕完全显示完弹幕,就可以添加下一条了, +1为了用一定缓冲距离
  83. var fullShowTime = Math.floor($(div).width() / $(this).width() * defaults.showTime);
  84. setTimeout(function() {
  85. dm_line_empty[line] = true;
  86. }, fullShowTime);
  87. //删除显示完的弹幕
  88. setTimeout(function() {
  89. $(‘#txt_dm‘ + id).remove();
  90. }, hideTime);
  91. }
  92. return this;
  93. }
  94. })(jQuery);

需要注意的是

  1. 中文与英文混合的情况下,宽度计算需要注意,经过测试,得出5/8的比例刚刚好,否则不是太长,就是不够导致换行。
  2. 使用var dm_line_empty = Array(dm_lines);来对每行的弹幕能否显示做判断,添加弹幕的时候,哪行空闲就忘哪行添加数据,提高屏幕的利用率。
  3. 弹幕移动使用的是velocity.js,否则效率太低,在移动设备上卡的飞起。
  4. 并没有实现屏幕上中下的弹幕模式……

使用起来非常的简单,样式自行设置即可

  1. var dm = $(‘.container‘).danmu();
  2. dm.add(‘123‘);
  3. dm.add(‘双击66666666666666666‘);
  4. dm.add(‘老铁没毛病!‘)

模式

插件是有了,但是应用到业务上还需要我们自己做空置,一般来说有2个模式,供不同场景使用

这里设计弹幕的基础数据库格式为,至于扩展和业务字段自行添加。

id:自增

txt:用户输入的弹幕

time:用户提交时的总秒数,进入页面就开始从0每秒自增,提交时就是当时的总数,如果是视频,就是当时的播放时间。

type:弹幕模式,可以包括从左往右,从右往左,屏幕上方,中间,下方等等。由于只实现了一种,这个字段我们这里去掉。

可以考虑time,type作为复合索引。

无限循环模式

这应该是大多情况使用的模式,因为H5活动不像看视频,不可能按照发布时间来展示弹幕,因为也许用户发布一条评论的时间有20秒,那么岂不是前20秒整个弹幕都空空的?所以我们首要目的就是呈现那种热闹劲,一次性的读取全部弹幕,如果数量过多,可以做一些取舍,循环播放,每隔一定时间,重复显示弹幕。

  1. //--------------------------------重复展示弹幕----------------------------------------
  2. //重复展示时间间隔,如果弹幕少,就设置小一些,这样重复的多。
  3. var recycle_time = 10;
  4. var load_recycle_interval;
  5. var recycle_load_timeout;
  6. //重复展示弹幕
  7. function dmRecycleStart(data) {
  8. for (var i = 0; i < data.length; i++) {
  9. var id = data[i][‘id‘];
  10. var txt = data[i][‘txt‘];
  11. //闭包&立即执行传递参数,返回新的方法,否则add方法会被立即执行
  12. recycle_load_timeout[i] = setTimeout(function(txt, id) {
  13. return function() {
  14. dm.add(txt, id);
  15. };
  16. }(txt, id), 1000 * Math.floor(Math.random() * recycle_time) + 1); //随机时间点显示文字
  17. }
  18. }
  19. recycle_load_timeout = Array(data.length);
  20. //先显示一次
  21. dmRecycleStart(data);
  22. //然后每隔一段时间都展示一次
  23. load_recycle_interval = setInterval(function() {
  24. dmRecycleStart(data);
  25. }, recycle_time * 1000);

时间线模式

这种模式就是和视频弹幕一样的模式了,按照用户发送弹幕的时间进行播放, 我们需要设置个定时器,每一秒显示一次该时间点的弹幕,每隔一段时间读取时间段内的所有弹幕。

我这里设计时,为了方便直接调用,服务器做了些格式转化,预先把消息按照时间点进行分组了,php参考代码如下:

  1. public function getdm()
  2. {
  3. $start_time = I(‘get.start_time‘);
  4. $end_time = I(‘get.end_time‘);
  5. $mode = I(‘get.type‘);
  6. $db_result = M(‘dm‘)->query("select id,txt,ptime from dm where and ptime between %d and %d" and type=%d, $start_time, $end_time, $type);
  7. $ret = array();
  8. //根据时间进行分组
  9. foreach ($db_result as $key => $value) {
  10. $ret[$value[‘ptime‘]][] = array($value[‘id‘], $value[‘txt‘]);
  11. }
  12. $this->ajaxReturn($ret);
  13. }

JS代码参考如下:

  1. //---------------------------------时间线弹幕-----------------------------------------
  2. var dm_get_count = 0;
  3. //用户提交弹幕的时候,时间参数可以以此为基准。
  4. var dm_time = 0;
  5. var load_interval;
  6. var load_timeout;
  7. //加载弹幕
  8. function dmLoadTimeLine() {
  9. //每秒钟执行一次,更新时间,这里设置为每30秒为间隔显示一次弹幕(16秒开始预加载),根据时间点投放
  10. load_interval = setInterval(function() {
  11. if (dm_time % 16 == 0) {
  12. var start_time = dm_get_count * 30;
  13. var end_time = (dm_get_count + 1) * 30;
  14. //中间预加载
  15. // $.get(‘./getdm‘, {
  16. // start_time: start_time,
  17. // end_time: end_time,
  18. // type: typeid,
  19. // }, function(data) {
  20. dm_pre = line_data;
  21. console.log(start_time + ‘-‘ + end_time + ‘预加载完成‘);
  22. //第一次加载完成直接显示
  23. if (dm_get_count == 0) {
  24. dmTimeLineStart();
  25. }
  26. dm_get_count++;
  27. // });
  28. } else if (dm_time % 30 == 0) {
  29. dmTimeLineStart();
  30. }
  31. dm_time++;
  32. }, 1000);
  33. //每秒1个弹幕,30秒则有30个
  34. load_timeout = Array(30);
  35. }
  36. //时间线弹幕
  37. function dmTimeLineStart() {
  38. var start_time = dm_get_count * 30;
  39. var end_time = (dm_get_count + 1) * 30;
  40. console.log(start_time + ‘-‘ + end_time + ‘显示弹幕‘);
  41. //深度拷贝数组,如果是从接口获取数据,最好拷贝一次。
  42. var dm_current = $.extend(true, {}, dm_pre);
  43. //时间点内显示弹幕
  44. for (var i = start_time; i < end_time; i++) {
  45. if (dm_current[i] != null) {
  46. for (var j = 0; j < dm_current[i].length; j++) {
  47. var id = dm_current[i][j][‘id‘];
  48. var txt = dm_current[i][j][‘txt‘];
  49. //内部函数立即执行,闭包传递参数,
  50. load_timeout[i] = setTimeout(function(txt, id) {
  51. return function() {
  52. dm.add(txt, id)
  53. };
  54. }(txt, id), 1000 * i + 1); //指定时间点显示文字
  55. }
  56. }
  57. }
  58. }

停止显示弹幕

当用户关闭弹幕时,可以用下列代码,也说明了上面代码中一些参数的用处

  1. function dmStop() {
  2. clearInterval(load_interval);
  3. clearInterval(load_recycle_interval);
  4. dm_time = 0;
  5. dm_get_count = 0;
  6. dm_pre = Array();
  7. if (load_timeout != undefined) {
  8. for (var i = 0; i < load_timeout.length; i++) {
  9. clearTimeout(load_timeout[i]);
  10. }
  11. }
  12. if (recycle_load_timeout != undefined) {
  13. for (var i = 0; i < recycle_load_timeout.length; i++) {
  14. clearTimeout(recycle_load_timeout[i]);
  15. }
  16. }
  17. }

最终demo效果如下:

demo地址:

https://github.com/leestar54/h5-demo/blob/master/danmu.html

时间: 2024-10-25 03:46:53

那些H5用到的技术(4)——弹幕的相关文章

那些H5用到的技术(1)——素材加载

编码环境前言什么时候用到素材加载?loading提示,让用户等待图片的加载音频的加载利用神器PreloadJS总结 编码环境 Sublime Text 3 插件包括: Autoprefixer 自动补全CSS ColorPicker 颜色选择器 ConvertToUTF8 转码 GBK Support 支持GBK HTML-CSS-JS Prettify 前端代码格式化 SublimeCodeIntel 最好用的自动补全 Chrome 57.0.2950.5 m 用来预览以及调试 gifcam

H5 视频直播相关技术

一.移动视频直播发展 大家首先来看下面这张图: 可以看到,直播从 PC 到一直发展到移动端,越来越多的直播类 App 上线,同时移动直播进入了前所未有的爆发阶段,但是对于大多数移动直播来说,还是要以 Native 客户端实现为主,但是 H5 在移动直播端也承载着不可替代的作用,例如 H5 有着传播快,易发布的优势,同时最为关键的时 H5 同样可以播放直播视频. 大家可以看下面这张大概的实现图 完整的直播可以分为以下几块: 视频录制端:一般是电脑上的音视频输入设备或者手机端的摄像头或者麦克风,目前

那些H5用到的技术(2)——音频和视频播放

前言audio标签Web Audio API自动播放的问题背景音乐的实现立即播放的问题SoundJSvideo标签播放样式的问题格式的问题总结 前言 正常情况,除了非常简陋的小功能H5,音乐播放是必不可少的,对于带有互动的小游戏,还必须有各种酷炫的音效,这就必须用到音频使用了,而对于视频,主要用到过场动画和品牌广告宣传. audio标签 audio 标签是 HTML 5 的新标签. 其中controls属性可以向用户显示控件,是浏览器自带的样式,否则audio是隐藏不显示的,但是每个浏览器自带样

java 视频播放 弹幕技术 视频弹幕 视频截图 springmvc mybatis SSM

A代码编辑器,在线模版编辑,仿开发工具编辑器,pdf在线预览,文件转换编码B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,快速开发利器)+快速表单构建器 freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本,处理类,service等完整模块C 集成阿里巴巴数据库连接池druid??数据库连接池??阿里巴巴的 druid.Druid在监控.可扩展性.稳定性和性能方面都有明显的优势D 集成安全权限框架shiro??Shiro 是一个用 Java 语言

新颖交互形式的H5案例浅析(技术分析)

最近我们前端这边搜集了50个比较优秀的H5. 那我这边呢,根据技术的分类,找出其中十个有代表性的案例,给大家解析一下他们技术的实现方案. 设计师也可以根据技术实现作为你们提供的素材参考 因为我主要是对技术分类的介绍,所以只取了不同技术实现的案例,同一种技术实现的不同的设计风格我就不列举出来了. 首先稍微提一下,其中包含的技术主要分为:createjs/thresjs/video内联播放/ 首先第一个呢,是之前腾讯爸爸出品的腾讯动漫的一个APP宣传的H5,这个H5是由腾讯内的TGideas团队完成

那些H5用到的技术(6)——数字滚动特效

前言原理源码使用方式补充CountUp.js 前言 会有这么一种情况,H5页面需要进行数字统计展示,以此来强调产品or工作的成果.如果只是静态显示一个数字,总是感觉生硬.对比如下: 是不是瞬间高大上了呢? 这个效果我是在开源中国上找到的 https://www.oschina.net/code/snippet_2380148_52928 感谢馒头同学. 原理 1.如上图可知,代码将每个数字生成了一竖0-9和小数点的队列.如果需要滚动999,那么就会生成3竖 2.由于有height的限制,所以通过

手机QQ会员H5加速方案——sonic技术内幕

版权声明:本文由况鹰原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/141 来源:腾云阁 https://www.qcloud.com/community 目前移动端越多越多的网页开始H5化,一方面可以减少安装包体积,另一方面也方便运营.但是相对于原生界面而言,H5的慢速问题一定被大家所诟病,针对这个问题,目前手Q存在几种方案,最常见的便是离线包方案,但离线包存在几个问题: 滞后性,内容显示不及时: 覆盖率,很难达到10

才一年,H5的发展就成这样了......

关于H5的发展,分享几个最近看到的惊人数据和新闻: 1.截至2015,有80%的App将全部或部分基于HTML5.这意味着大部分App的内容都将是以网页的形式呈现,典型的例子包括微信.Facebook.Twitter等.(数据来源:国际科技媒体 ReadWriteWeb,2015) 2.浏览量最高的1000个H5作品中,42%是心灵鸡汤,最高17,358,480 uv:27%是测试题,最高49,940,339 uv:15%是社交互动游戏,最高2,892,047 uv; 5%是大型品牌宣传,最高5

“小程序+直播”怎样搅动音视频技术生态?

责编 / 王宇豪 策划 / LiveVideoStack 12月26日晚间,微信小程序开放了直播能力,并首先向社交.教育.医疗.政务民生.金融等五大应用场景开放.与原生App应用和基于浏览器的H5应用相比,小程序直播会对音视频技术生态带来哪些影响?微信天生的流量优势会给开发者和运营带来机会还是陷阱?LiveVideoStack邀请了若干位有代表性的技术人,分享各自的观点与思考. LiveVideoStack:对于小程序提供的这种实时音视频功能,它是否能满足我们一般的直播需求呢?比如它的延迟大致能