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

简介: 前言这个需求如题,大体上是将文章的评论数据,在文章的首图上面以弹幕的形式出现。当时在做这个需求的时候,花了挺多精力的,踩了很多坑,现将弹幕的实现思路写出来,如果喜欢的话可以点波赞/关注,支持一下,希望大家看完本文可以有所收获。实现原理:实现弹幕的原理,并不算太复杂,耗费一些时间,怼一怼应该都可以做出来。获取弹幕数据。将弹幕设置为四个通道,每个通道最多只能出现两条弹幕。使用setInterval动态设置dom的left属性。使用dom的offsetWidth和屏幕的宽度判断元素是否滚动超出屏幕,然后移除dom。

image.png

前言

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


实现效果:

image.png

实现原理:

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

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

实现步骤:

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

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

关于这里的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)
   }
 }


结语

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

目录
相关文章
|
27天前
|
存储 监控 安全
前端框架的数据驱动方式如何保证数据的安全性?
总之,前端框架的数据驱动方式需要综合运用多种手段来保证数据的安全性。从传输、存储、访问控制到防范攻击等各个方面进行全面考虑和实施,以确保用户数据的安全可靠。同时,不断加强安全管理和技术创新,以应对不断变化的安全挑战。
105 60
|
2月前
|
JSON 前端开发 Java
震惊!图文并茂——Java后端如何响应不同格式的数据给前端(带源码)
文章介绍了Java后端如何使用Spring Boot框架响应不同格式的数据给前端,包括返回静态页面、数据、HTML代码片段、JSON对象、设置状态码和响应的Header。
161 1
震惊!图文并茂——Java后端如何响应不同格式的数据给前端(带源码)
|
2月前
|
监控 JavaScript 前端开发
前端的混合之路Meteor篇(六):发布订阅示例代码及如何将Meteor的响应数据映射到vue3的reactive系统
本文介绍了 Meteor 3.0 中的发布-订阅模型,详细讲解了如何在服务器端通过 `Meteor.publish` 发布数据,包括简单发布和自定义发布。客户端则通过 `Meteor.subscribe` 订阅数据,并使用 MiniMongo 实现实时数据同步。此外,还展示了如何在 Vue 3 中将 MiniMongo 的 `cursor` 转化为响应式数组,实现数据的自动更新。
|
2月前
|
JSON 分布式计算 前端开发
前端的全栈之路Meteor篇(七):轻量的NoSql分布式数据协议同步协议DDP深度剖析
本文深入探讨了DDP(Distributed Data Protocol)协议,这是一种在Meteor框架中广泛使用的发布/订阅协议,支持实时数据同步。文章详细介绍了DDP的主要特点、消息类型、协议流程及其在Meteor中的应用,包括实时数据同步、用户界面响应、分布式计算、多客户端协作和离线支持等。通过学习DDP,开发者可以构建响应迅速、适应性强的现代Web应用。
|
2月前
|
JavaScript 前端开发 Python
django接收前端vue传输的formData图片数据
django接收前端vue传输的formData图片数据
62 4
|
2月前
|
NoSQL 前端开发 MongoDB
前端的全栈之路Meteor篇(三):运行在浏览器端的NoSQL数据库副本-MiniMongo介绍及其前后端数据实时同步示例
MiniMongo 是 Meteor 框架中的客户端数据库组件,模拟了 MongoDB 的核心功能,允许前端开发者使用类似 MongoDB 的 API 进行数据操作。通过 Meteor 的数据同步机制,MiniMongo 与服务器端的 MongoDB 实现实时数据同步,确保数据一致性,支持发布/订阅模型和响应式数据源,适用于实时聊天、项目管理和协作工具等应用场景。
|
2月前
|
存储 前端开发 API
前端开发中,Web Storage的存储数据的方法localstorage和sessionStorage的使用及区别
前端开发中,Web Storage的存储数据的方法localstorage和sessionStorage的使用及区别
115 0
|
2月前
|
前端开发 Java 数据库
springBoot:template engine&自定义一个mvc&后端给前端传数据&增删改查 (三)
本文介绍了如何自定义一个 MVC 框架,包括后端向前端传递数据、前后端代理配置、实现增删改查功能以及分页查询。详细展示了代码示例,从配置文件到控制器、服务层和数据访问层的实现,帮助开发者快速理解和应用。
|
4月前
|
开发者 Java
JSF EL 表达式:乘技术潮流之风,筑简洁开发之梦,触动开发者心弦的强大语言
【8月更文挑战第31天】JavaServer Faces (JSF) 的表达式语言 (EL) 是一种强大的工具,允许开发者在 JSF 页面和后台 bean 间进行简洁高效的数据绑定。本文介绍了 JSF EL 的基本概念及使用技巧,包括访问 bean 属性和方法、数据绑定、内置对象使用、条件判断和循环等,并分享了最佳实践建议,帮助提升开发效率和代码质量。
56 0
|
4月前
|
前端开发 API 开发者
JSF与RESTful服务的完美邂逅:如何打造符合现代Web潮流的数据交互新体验
【8月更文挑战第31天】随着互联网技术的发展,RESTful架构风格因其实现简便与无状态特性而在Web服务构建中日益流行。本文探讨如何结合JavaServer Faces (JSF) 和 JAX-RS 构建RESTful API,展示从前端到后端分离的完整解决方案。通过定义资源类、配置 `web.xml` 文件以及使用依赖注入等步骤,演示了在JSF项目中实现RESTful服务的具体过程,为Java开发者提供了实用指南。
43 0