jQuery实现简单弹幕效果


Posted in jQuery onNovember 28, 2019

本文实例为大家分享了jQuery实现弹幕效果的具体代码,供大家参考,具体内容如下

话不多说吧,直接看效果吧:

jQuery实现简单弹幕效果

主要思路

其实弹幕的主要思路很简单,就是将div从右向左移动,直到完全移除屏幕之后,将当前div从body中移除,这里我采用了面向对象的思想来处理,具体js代码如下:

JS

/**
 * 弹幕
 */
$(function () {

  function BarrageManager (options) {

    this.opts = {
      url    : './res/danmu.json',
      loadDelay : 5000 , // 轮询时间间隔
    }

    $.extend( this.opts , options);
    this.bc = new BarrageCollection();
  }

  BarrageManager.prototype.load = function () {
    var self = this ;
    $.getJSON(self.opts.url , function (data) {
      if(data.data.length > 0) {
        for(var i = 0 ; i < data.data.length ; i++) {
          var item = data.data[i] ;
          self.bc.add(new Barrage({
            id:item.id,
            name:item.fromUserName,
            text:item.content,
            icon:item.fromUserIcon ? item.fromUserIcon : './images/head-icon.png'
          }));
        }
        self.loop();
      }
    });
  }

  BarrageManager.prototype.loop = function () {
    var len = this.bc.mq.length , self = this ;
    while (len--) {
      this.bc.mq[len].start(this.bc , len);
    }  

    setTimeout(function () {
      self.load();
    } , this.opts.loadDelay);

  }

  function BarrageCollection () {
    this.mq = [] ;
  }

  BarrageCollection.prototype.add = function (barrage) {
    this.mq.push(barrage);
  }

  BarrageCollection.prototype.remove = function (barrage) {
    var index = this.mq.findIndex(function (item) {
      return barrage.opts.id == item.opts.id ;
    });
    if(index != -1) {
      this.mq.splice(index , 1);
    }
    barrage.opts.$el.remove();
  }

  function Barrage (options) {
    this.opts = {
      $el     : null ,
      left    : 0 ,
      bgColor   : [Math.floor(Math.random()*255),Math.floor(Math.random()*255),Math.floor(Math.random()*255)] ,
      offset   : 50 ,   // 使弹幕完全移出屏幕外
      duration  : 10000 ,  // 弹幕从右往左移动的时间 
      delayTime  : 1000 ,  // 弹幕延迟移动时间
    };
    $.extend( this.opts , options);
    this.init();
  }

  Barrage.prototype.init = function () {

    this.opts.$el = $("<span><img src="+this.opts.icon+"><em>"+this.opts.name+":</em>"+this.opts.text+"</span>");

    var top = Math.ceil(Math.random() * 10 );
    this.opts.$el.css({
      top:top * 40 +'px',
      backgroundColor:"rgb("+this.opts.bgColor.join(",")+")"
    });

    var delay = Math.ceil(Math.random()*10);
    this.opts.delayTime *= Math.abs(delay - 5);

    var dur = Math.ceil(Math.random() * 10);
    this.opts.duration += dur * 1000 ; 

    $('#barrage-wrapper').append(this.opts.$el);
    this.opts.left = -this.opts.$el.width() - this.opts.offset ;
  }

  Barrage.prototype.start = function (bc , index) {
    var self = this ;
    bc.mq.splice(index , 1);
    setTimeout(function () {
      self.move(bc);
    }, this.opts.delayTime);
  }

  Barrage.prototype.move = function (bc) {
    var self = this ;
    this.opts.$el.animate({
      left:this.opts.left+'px'
    } , this.opts.duration ,"linear" , function () {
      bc.remove(self); 
    });
  }

  new BarrageManager().load();
});

代码分析

首先我定义了3个类

  • BarrageManager : 弹幕管理类
  • BarrageCollection :弹幕集合类
  • Barrage : 弹幕类

BarrageManager 中的方法:

  • load : 加载弹幕数据
  • loop: 间隔指定时间循环加载数据

load 方法就不加以说明了,主要讲一下 loop方法:

BarrageManager.prototype.loop = function () {
    var len = this.bc.mq.length , self = this ;
    while (len--) {
      this.bc.mq[len].start(this.bc , len);
    }  

    setTimeout(function () {
      self.load();
    } , this.opts.loadDelay);

  }

通过while循环,将弹幕集合中所有弹幕对象取出,并调用他的start方法,开启弹幕动画,然后每间隔指定时间再去调用一次load方法,生成新的弹幕对象,并添加到弹幕结合中。

PS: 这里其实最好使用socket,然服务端主动推送,而不是客户端通过http进行轮询,我这里主要讲解实现弹幕的思路,至于怎么获取数据,这个大家可以去优化,不过我可以推荐一个socket第三方包 socket.io 这个库挺厉害的,大家可以去看看。

BarrageCollection 中的方法:

  • add : 添加弹幕
  • remove: 移除弹幕

BarrageCollection 中的方法其实就是对数据进行了一层包装操作而已,其实也可以不要这一层。代码也相对简单,我就不多说了(嘻嘻,大家现在水平都不错,一眼就能看明白对吧)。

Barrage 中的方法:

  • init : 初始化参数
  • start: 开启弹幕移动的动画
  • move: 执行弹幕移动动画

其实Barrage中的方法也相对简单,首先在Barrage中定义了它所需要的属性,在new Barrage() 的时候,传递参数,然后调用init方法进初始化,生成dom,设置弹幕块当前的背景颜色,以及屏幕的垂直位置如下:

var top = Math.ceil(Math.random() * 10 );
this.opts.$el.css({
   top:top * 40 +'px',
   backgroundColor:"rgb("+this.opts.bgColor.join(",")+")"
});

随机生成top值,为了避免弹幕块在同一垂直位置出现。
然后设置弹幕块从右往左移动时所需要的时间,以及延迟开始移动的时间

// 设置弹幕块延迟移动的时间
var delay = Math.ceil(Math.random()*10);
this.opts.delayTime *= Math.abs(delay - 5);
// 设置弹幕块移动的时长 
var dur = Math.ceil(Math.random() * 10);
this.opts.duration += dur * 1000 ;

设置这两个参数,是为了不让弹幕块在进入屏幕的时候同时出现,并且如果移动速度相同,就感觉整体在一起移动,效果不太好。

最后将弹幕块的dom添加在html中,并计算出left值

$('#barrage-wrapper').append(this.opts.$el);
this.opts.left = -this.opts.$el.width() - this.opts.offset ;

left值也就是弹幕块要移动的距离,这里我加了一个偏移量offset(这个随意),可能我css设置有点问题,如果不加这个,弹幕块在还没完全移出屏幕的时候就从html中移除了,会突然变没,有点突兀,因此加了一个偏移量,保证弹幕块完全移出屏幕

当弹幕块都初始化完成了之后,调用start方法,开始移动

Barrage.prototype.start = function (bc , index) {
    var self = this ;
    bc.mq.splice(index , 1);
    setTimeout(function () {
      self.move(bc);
    }, this.opts.delayTime);
  }

move方法则是使用jq的animate方法来实现dom的移动动画

Barrage.prototype.move = function (bc) {
    var self = this ;
    this.opts.$el.animate({
      left:this.opts.left+'px'
    } , this.opts.duration ,"linear" , function () {
      bc.remove(self); 
    });
  }

在弹幕完全移出屏幕时,也就是动画结束时,将当前弹幕dom从html中移除。整体的思路也就是这样,是不是很简单,不过在这里我对start方法中的这段代码进行说明一下:

bc.mq.splice(index , 1);

我在开始动画之前,首先将当前弹幕对象从BarrageCollection 中移出了,按理说应该在弹幕完全移出屏幕时才执行这个操作才对,其实是因为,当我们在调用 BarrageManager 中的loop方法循环获取弹幕数据的时候,会改变BarrageCollection 中弹幕集合的长度,这时候会造成传递到 start方法中的index值可能会大于集合的长度,从而报错,因此我在每次调用start的时候就将当前弹幕对象从集合中移除,确保集合每次都是空的,从而不会有其他影响。

源码下载:jQuery实现简单弹幕效果

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

jQuery 相关文章推荐
jQuery EasyUI 组件加上“清除”功能实例详解
Apr 11 jQuery
jQuery Easyui Treegrid实现显示checkbox功能
Aug 08 jQuery
jQuery选择器之表单元素选择器详解
Sep 19 jQuery
jQuery实现可兼容IE6的淡入淡出效果告警提示功能示例
Sep 20 jQuery
jQuery实现验证表单密码一致性及正则表达式验证邮箱、手机号的方法
Dec 05 jQuery
CSS3结合jQuery实现动画效果及回调函数的实例
Dec 27 jQuery
基于jquery.page.js实现分页效果
Jan 01 jQuery
jQuery创建及操作xml格式数据示例
May 26 jQuery
JQuery通过后台获取数据遍历到前台的方法
Aug 13 jQuery
jquery 遍历hash操作示例【基于ajax交互】
Oct 12 jQuery
Jquery异步上传文件代码实例
Nov 13 jQuery
jQuery实现数字华容道小游戏(实例代码)
Jan 16 jQuery
jQuery实现轮播图效果
Nov 26 #jQuery
jQuery与原生JavaScript选择HTML元素集合用法对比分析
Nov 26 #jQuery
高效jQuery选择器的5个技巧实例分析
Nov 26 #jQuery
jquery使用echarts实现有向图可视化功能示例
Nov 25 #jQuery
jQuery Raty星级评分插件使用方法实例分析
Nov 25 #jQuery
jquery 插件重新绑定的处理方法分析
Nov 23 #jQuery
JQuery使用属性addClass、removeClass和toggleClass实现增加和删除类操作示例
Nov 18 #jQuery
You might like
数据库相关问题
2006/10/09 PHP
POSIX 风格和兼容 Perl 风格两种正则表达式主要函数的类比(preg_match, preg_replace, ereg, ereg_replace)
2010/10/12 PHP
实现获取http内容的php函数分享
2014/02/16 PHP
PHP获取当前所在目录位置的方法
2014/11/26 PHP
php中smarty实现多模版网站的方法
2015/06/11 PHP
thinkPHP多域名情况下使用memcache方式共享session数据的实现方法
2016/07/21 PHP
Zend Framework入门教程之Zend_Mail用法示例
2016/12/08 PHP
php使用 readfile() 函数设置文件大小大小的方法
2017/08/11 PHP
简单实现php上传文件功能
2017/09/21 PHP
PHP基于递归算法解决兔子生兔子问题
2018/05/11 PHP
解析jquery获取父窗口的元素
2013/06/26 Javascript
Nodejs极简入门教程(一):模块机制
2014/10/25 NodeJs
js实现文本框宽度自适应文本宽度的方法
2015/08/13 Javascript
JS+CSS实现鼠标滑过时动态翻滚的导航条效果
2015/09/24 Javascript
AngularJS中实现显示或隐藏动画效果的方式总结
2015/12/31 Javascript
第六章之辅组类与响应式工具
2016/04/25 Javascript
简单实现vue验证码60秒倒计时功能
2017/10/11 Javascript
babel之配置文件.babelrc入门详解
2018/02/22 Javascript
Element 默认勾选表格 toggleRowSelection的实现
2019/09/04 Javascript
vue中的mescroll搜索运用及各种填坑处理
2019/10/30 Javascript
JavaScript位置参数实现原理及过程解析
2020/09/14 Javascript
nuxt 每个页面head标签内容设置方式
2020/11/05 Javascript
python sort、sorted高级排序技巧
2014/11/21 Python
python操作ie登陆土豆网的方法
2015/05/09 Python
实例讲解Python中global语句下全局变量的值的修改
2016/06/16 Python
Django实现文件上传下载功能
2019/10/06 Python
Python SSL证书验证问题解决方案
2020/01/13 Python
Python基于模块Paramiko实现SSHv2协议
2020/04/28 Python
解决pyinstaller 打包exe文件太大,用pipenv 缩小exe的问题
2020/07/13 Python
Python爬虫过程解析之多线程获取小米应用商店数据
2020/11/14 Python
CSS3 filter(滤镜)实现网页灰色或者黑色模式的示例代码
2021/02/24 HTML / CSS
同事吵架检讨书
2014/02/05 职场文书
销售员未完成销售业绩的检讨书
2014/10/12 职场文书
欠条范文
2015/07/03 职场文书
《乌鸦喝水》教学反思
2016/02/19 职场文书
描述鲁迅的名言整理,一生受用
2019/08/08 职场文书