How the front end converts data into barrage effect

foreword

This requirement is the same as the title. Generally speaking, the comment data of the article is displayed in the form of a barrage above the first picture of the article. At that time, when I was doing this requirement, I spent a lot of energy and stepped on a lot of pits. Now I will write the realization idea of ​​​​the barrage. If you like it, you can like/follow and support it. I hope you can read this article. harvested.

Personal blog to find out: obkoro1.com


Realize the effect:

Implementation principle:

The principle of realizing the barrage is not too complicated, it takes some time, and it should be possible to do it.

  1. Get the bullet screen data.
  2. Set the barrage to four channels, and each channel can only appear at most two barrages.
  3. Use setIntervaldynamically set domproperties left.
  4. Use offsetWidththe width of the dom and the screen to determine if the element scrolls beyond the screen, then remove the dom.

Implementation steps:

1. First look at htmlthe structure.

    <div class="detailImg">
        <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在各自的水平线上,形成四个通道->

Regarding the css style here, the key points are mentioned above, just pay attention to how the above channel is formed, and that's it. The specific style will not be posted, just come according to their own needs.

2. Obtain the data required by the barrage.

To achieve the barrage effect, you must have data, and here is the request.

When acquiring data, consider the amount of data. It is impossible to acquire all of the data at one time . You can acquire a part of it at a time. When the data is to be loaded, request the data again.

Here, it is necessary to record whether all the data requests are completed . If the request is completed, no more data can be sent, and all the data obtained before can be used directly.

3. Execute the function of the barrage.

After the barrage data is obtained, the function of the barrage operation is executed, because when I wrote the barrage function, I set a lot of data states. Here I will briefly talk about the implementation ideas and key parts of the code.

The barrage function includes the following functions:

  1. Get data regularly (judging whether the data is loaded)

  2. Timely launch the barrage (judging whether the channel is idle), pass in the content required by the barrage, user avatar, etc.

  3. Create the dom content, generate the bullet chat div according to the passed parameters, set the style attribute, and insert the div into the corresponding dom according to the subscript of the control bullet chat data array.

  4. Use the timer to move the dom, here is to define the movement speed of the bullet screen according to the content length.

  5. In the process of moving the barrage, it is judged whether the four channels are in an idle state. When the dom is moved out of the screen, the dom is moved and the timer is cleared.

     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)
       }
     }
    

Epilogue

I implemented this barrage requirement as above. Looking back at the implementation, I found that there are still many places that can be optimized and split. If there are better implementation ideas and what are the mistakes in this article, please leave a message in the comment area.

I hope that friends who have read it can click like/follow, your support is the greatest encouragement to me.

Finally : If you need to reprint, please put a link to the original text and sign it. It's not easy to code, thank you for your support! I write the article with the mentality of exchange records, and I don't want to tear it up, but welcome pointers.

Personal blog and Nuggets personal homepage

Follow my subscription number to learn and grow together.

Above 2018.4.29

References:

Pure js to achieve barrage effect

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325368638&siteId=291194637