前端将数据转化为弹幕效果的实现方式

时间: 2018-05-07阅读: 232标签: 数据

前言

这个需求如题,大体上是将文章的评论数据,在文章的首图上面以弹幕的形式出现。当时在做这个需求的时候,花了挺多精力的,踩了很多坑,现将弹幕的实现思路写出来,如果喜欢的话可以点波赞/关注,支持一下,希望大家看完本文可以有所收获。

个人博客了解一下:obkoro1.com


实现效果:



实现原理:

实现弹幕的原理,并不算太复杂,耗费一些时间,怼一怼应该都可以做出来。

  1. 获取弹幕数据。
  2. 将弹幕设置为四个通道,每个通道最多只能出现两条弹幕。
  3. 使用setInterval动态设置dom的left属性。
  4. 使用dom的offsetWidth和屏幕的宽度判断元素是否滚动超出屏幕,然后移除dom


实现步骤:

1. 首先看一下html的结构。

<div>
    <img src="url"/>
    <div id="barrageDiv">
        <div id="barrageLayer1"></div>
        <div id="barrageLayer2"></div>
        <div id="barrageLayer3"></div>
        <div id="barrageLayer4"></div>
    </div>
  </div>
  <!--detailImg 设置relative, barrageDiv设置z-index在图片上面,以及图片的位置-->
  <!---barrageLayer1~4 主要设置了一个top属性让四个div在各自的水平线上,形成四个通道->

关于这里的css样式,关键点都在上面说了,就注意一下上面通道是怎样形成的,就可以了。具体的样式也就不贴出来了,就根据各自的需求来吧。

2.获取弹幕所需要的数据。

要实现弹幕效果肯定需要有数据,这里就是发请求了。

获取数据时,要考虑数据量,一次不可能全部都获取,可以一次获取一部分,当数据要加载完的时候,再次请求数据。

这里要记录数据数据是否全部请求完成,如果请求完成,就可以不再发送数据,直接用之前获取的全部数据就可以了。

3.执行弹幕的函数。

弹幕数据获取后,就执行弹幕运行的函数,因为我在写弹幕函数的时候,设置了很多数据状态,这里就大概讲一下实现思路和关键部分代码。

弹幕函数包括的功能:

  1. 定时获取数据(判断数据是否加载完毕)
  2. 定时发射弹幕(判断通道是否闲置),传入弹幕所需要的内容,用户头像等。
  3. 创建dom内容,根据传参生成弹幕div,设置style属性,根据控制弹幕数据数组的下标将div插入对应的dom中。
  4. 采用定时器移动dom,这里是根据内容长度定义弹幕的移动速度。
  5. 移动弹幕的过程中判断四个通道是否处于闲置状态,当dom移动出了屏幕,移动dom并且清除定时器。

function barrage(){
    //第一部分先判断数据是否加载完成 这里是一个定时器,设置为15秒。
    //如果数据还未加载完毕,就再次运行请求数据的接口,请求的页数可以 数组/每次请求的条数+1
    //数据加载完毕就清除定时器。(我将定时器都保存在vue 组件的data里面) 清除的时候clearInterval(this.data);

    //定时发射
     _this.barrageStatus.divStatus.intervalid=setInterval( selfTime,1100);
     function selfTime() { 
        if(_this.dataNum>=_this.barrageStatus.data.length){
        //当dataNum大于等于数组的数量时,弹幕从头再来一遍
          _this.dataNum=0;
        }
    //设置四个通道的变量,当这几个变量为false的时候,才可发射
      if(divStatus.div1===false){
        //这里只演示其中一个变量
        divStatus.div1=true;
        _this.dataNum++;                        
       return barrageOut(_this.barrageStatus.data[_this.dataNum-1].content,_this.barrageStatus.data[_this.dataNum-1].commentator.headImgUrl,_this.dataNum);
      }
  };

  // 创建弹幕内容,自定义弹幕移动速度
  function barrageOut(text,imgUrl,num) { 
    //text:弹幕的内容,imgUrl:用户的头像,num:数组的第几个
    if(num%4==1){ 
    //根据数组下标 创建对应通道的节点 这里也演示其中一个
      barrageLayer=document.getElementById('barrageLayer1');
    }

    // 创建dom内容 定义dom style样式
    let divBox = document.createElement('div');
    let divBoxImg=document.createElement('span');
    let divBoxText=document.createElement('span');
    divBox.setAttribute('class','barrageDivClass');
    divBoxText.innerHTML=text;
    divBox.appendChild(divBoxImg);
    divBoxImg.setAttribute('class','barrageDivClass_img');
    divBoxImg.style.backgroundImage=`url(${imgUrl})`;
    divBox.appendChild(divBoxText);
    divBox.style.left=document.body.clientWidth+2000+'px';// 初始化left位置,一开始在屏幕的右侧
    barrageLayer.appendChild(divBox);

    // 定时器移动dom,形成弹幕
    let time,l=0;
    time= setInterval(function(){
      if(text.length<15){ 
      // 这里可以根据需求自定义弹幕加载的速度
        l=l-1;
      }else{
        l=l-2;
      }

      //通过减少left属性移动这个div 从右往左移动
     divBox.style.left = document.body.clientWidth+l+'px';
      let delDiv=()=>{
            if(num%4==1){ 
             //在移动弹幕的过程中判断四个通道是否处于闲置状态 这里只演示其中一个
              barrageLayer=document.getElementById('barrageLayer1');
              if(barrageLayer.childNodes.length<2){
                //判断弹幕数量,如果小于2,设为false,上面的定时器可以继续发射弹幕
                divStatus.div1=false;
              }else{
                divStatus.div1=true;
              }
          }
        }
      }
      if( l <= (0-divBox.offsetWidth-120) ){ 
        if(_this.barrageStatus.divStatus.switch==true){ //弹幕开关
          delDiv();
          if(l <= (0-divBox.offsetWidth-document.body.clientWidth) ){
            //不断减少left属性,当小于这个内容的宽度,并且滚了120的时候
              barrageLayer.removeChild(divBox); //移除dom
              clearInterval(time);//清除这个div的定时器
            }
        }else{
           clearInterval(time);//清除这个div的定时器
        }
      }
    },20)
  }
}


结语

这个弹幕需求,我是如上这么实现的,回头看看实现,发现还是有不少地方可以优化和拆分的,如果有更好的实现思路和本文有哪些错误,欢迎在评论区下面留言。

原文:http://obkoro1.com


Js中实现XML和String相互转化

XML是标准通用标记语言 (SGML) 的子集,非常适合 Web 传输。XML 提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。 这篇文章主要介绍Js中实现XML和String相互转化

JavaScript 那些不经意间发生的数据类型自动转换

JavaScript自动类型转换真的非常常见,常用的一些便捷的转类型的方式,都是依靠自动转换产生的。比如 转数字 : + x 、 x - 0 , 转字符串 : \"\" + x 等等。现在总算知道为什么可以这样便捷转换。

js算法_判断数字是否为素数/质数

质数又称素数。指在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数。比如100以内共25个,js实现代码如下。

js判断数字是奇数还是偶数的2种方法实现

奇数和偶数的判断是数学运算中经常碰到的问题,这篇文章主要讲解通过JavaScript来实现奇偶数的判断。2种判断方法:求余% 、&1

js判断类型为数字的方法实现总汇——原生js判断isNumber()

这篇文章主要整理关于js判断变量是否为数字的实现方法,我们把方法命名为isNumber,也就是说:对于整数,浮点数返回true,对于NaN或可转成NaN的值返回false。

js进制数之间以及和字符之间的转换

js要处理十六进制,十进制,字符之间的转换,发现有很多差不多且书写不正确的方法.一个一个实践才真正清楚如何转换,现在来记录一下它们之间转换的方法。

使用typeof obj===‘object’潜在的问题,并不能确定obj是否是一个对象?

在js中我们直接这样写typeof obj===‘object’有什么问题呢?发现Array, Object,null都被认为是一个对象了。如何解决这种情况,能保证判断obj是否为一个对象

javascript中的typeof返回的数据类型_以及强制/隐式类型转换

由于js为弱类型语言拥有动态类型,这意味着相同的变量可用作不同的类型。 typeof 运算符返回一个用来表示表达式的数据类型的字符串,目前typeof返回的字符串有以下这些: undefined、boolean、string、number、object、function、“symbol

JavaScript判断数据类型的多种方法【 js判断一个变量的类型】

js判断数据类型的多种方法,主要包括:typeof、instanceof、 constructor、 prototype.toString.call()等,下面就逐一介绍它们的异同。

原生JS数据绑定的实现

双向数据绑定是非常重要的特性 —— 将JS模型与HTML视图对应,能减少模板编译时间同时提高用户体验。我们将学习在不使用框架的情况下,使用原生JS实现双向绑定 —— 一种为Object.observe