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中each循环的简单回滚操作
May 05 jQuery
jQuery.ajax向后台传递数组问题的解决方法
May 12 jQuery
JQueryMiniUI按照时间进行查询的实现方法
Jun 07 jQuery
深入理解jquery的$.extend()、$.fn和$.fn.extend()
Jul 08 jQuery
jQuery实现可兼容IE6的淡入淡出效果告警提示功能示例
Sep 20 jQuery
使用JQuery实现图片轮播效果的实例(推荐)
Oct 24 jQuery
使用Ajax和Jquery配合数据库实现下拉框的二级联动的示例
Jan 25 jQuery
通过jquery toggleClass()属性制作文章段落更改背景颜色
May 21 jQuery
jQuery实现表单动态添加数据并提交的方法
Jul 19 jQuery
jQuery选择器之层次选择器用法实例分析
Feb 19 jQuery
jQuery实现日历效果
Sep 11 jQuery
jQuery实现简单全选框
Sep 13 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
德劲1102收音机的打理维修案例
2021/03/02 无线电
swfupload 多文件上传实现代码
2008/08/27 PHP
计算一段日期内的周末天数的php代码(星期六,星期日总和)
2009/11/12 PHP
让你成为更出色的PHP开发者的10个技巧
2011/02/25 PHP
php实现在线生成条形码示例分享(条形码生成器)
2013/12/30 PHP
phpnow php探针环境检测代码
2014/11/04 PHP
在Windows系统下使用PHP生成Word文档的教程
2015/07/03 PHP
php检查函数必传参数是否存在的实例详解
2017/08/28 PHP
Laravel5.1 框架响应基本用法实例分析
2020/01/04 PHP
用JavaScript获取网页中的js、css、Flash等文件
2006/12/20 Javascript
非常有用的40款jQuery 插件推荐(系列二)
2011/12/25 Javascript
浅析JavaScript中的变量复制、参数传递和作用域链
2016/01/13 Javascript
jquery.qtip提示信息插件用法简单实例
2016/06/17 Javascript
微信小程序 wxapp画布 canvas详细介绍
2016/10/31 Javascript
jquery 判断是否支持Placeholder属性的方法
2017/02/07 Javascript
Vue内容分发slot(全面解析)
2017/08/19 Javascript
使用MUI框架模拟手机端的下拉刷新和上拉加载功能
2017/09/04 Javascript
JavaScript html5 canvas实现图片上画超链接
2017/10/20 Javascript
基于Two.js实现星球环绕动画效果的示例
2017/11/06 Javascript
在Swiper内如何制作CSS3动画效果示例代码
2017/12/07 Javascript
vue使用Sass时报错问题的解决方法
2020/10/14 Javascript
[02:51]DOTA2英雄基础教程 艾欧
2014/01/13 DOTA
Python 面向对象 成员的访问约束
2008/12/23 Python
使用FastCGI部署Python的Django应用的教程
2015/07/22 Python
python爬虫实现教程转换成 PDF 电子书
2017/02/19 Python
对python多线程与global变量详解
2018/11/09 Python
Python 如何优雅的将数字转化为时间格式的方法
2019/09/26 Python
python机器学习实现决策树
2019/11/11 Python
详解Python中打乱列表顺序random.shuffle()的使用方法
2019/11/11 Python
如何写python的配置文件
2020/06/07 Python
python中的yield from语法快速学习
2020/11/06 Python
一份婚庆公司创业计划书
2014/01/11 职场文书
党委书记个人对照检查材料
2014/09/15 职场文书
2015年社区综治工作总结
2015/04/21 职场文书
行政处罚事先告知书
2015/07/01 职场文书
小学信息技术教学反思
2016/02/16 职场文书