原生JavaScript实现弹幕组件的示例代码_javascript技巧

来源:脚本之家  责任编辑:小易  

就是javasceipt弹出一个div,如果已经有div了,则向上移动一个div的height就可以了,下面的图片是啥追问谈正事www.zgxue.com防采集请勿采集本网。

前言

如今几乎所有的视频网站都有弹幕功能,那么今天我们就自己用原生 JavaScript 封装一个弹幕类。这个类希望有如下属性和实例方法:

属性 el容器节点的选择器,容器节点应为绝对定位,设置好宽高 height 每条弹幕的高度 mode 弹幕模式,half则为一半容器高度,top为三分之一,full为占满 speed弹幕划过屏幕的时间 gapWidth后一条弹幕与前一条弹幕的距离

方法 pushData 添加弹幕元数据 addData持续加入弹幕 start开始调度弹幕 stop停止弹幕 restart 重新开始弹幕 clearData清空弹幕 close关闭 open重新显示弹幕

PS:有一些自封装的工具函数就不贴出来了,大概知道意思就好

初始化

引入JavaScript文件之后,我们希望如下使用,先采取默认配置。

let barrage = new Barrage({ el: '#container'})

参数初始化:

function Barrage(options) { let { el, height, mode, speed, gapWidth, } = options this.container = document.querySelector(el) this.height = height || 30 this.speed = speed || 15000 //2000ms this.gapWidth = gapWidth || 20 this.list = [] this.mode = mode || 'half' this.boxSize = getBoxSize(this.container) this.perSpeed = Math.round(this.boxSize.width / this.speed) this.rows = initRows(this.boxSize, this.mode, this.height) this.timeoutFuncs = [] this.indexs = [] this.idMap = []}

先接受好参数然后初始化,下面看看getBoxSize和initRows

function getBoxSize(box) { let { height, width } = window.getComputedStyle(box) return { height: px2num(height), width: px2num(width) } function px2num(str) { return Number(str.substring(0, str.indexOf('p'))) }}

通过getComputedStyleapi计算出盒子的宽高,这里用来计算容器的宽高,之后也会用到。

function initRows(box, mode, height) { let divisor = getDivisor(mode) rows = Math.ceil(box.height * divisor / height) return rows}function getDivisor(mode) { let divisor = .5 switch (mode) { case 'half': divisor = .5 break case 'top': divisor = 1 / 3 break; case 'full': divisor = 1; break default: break; } return divisor}

根据高度算出弹幕应该有多少行,下面会有地方用到行数。

插入数据

有两种插入数据的方法,一种是添加源数据,一种是持续添加。先来看添加源数据的方法:

this.pushData = function (data) { this.initDom() if (getType(data) == '[object Object]') { //插入单条 this.pushOne(data) } if (getType(data) == '[object Array]') { //插入多条 this.pushArr(data) }}

this.initDom = function () { if (!document.querySelector(`${el} .barrage-list`)) { //注册dom节点 for (let i = 0; i < this.rows; i++) { let div = document.createElement('div') div.classList = `barrage-list barrage-list-${i}` div.style.height = `${this.boxSize.height*getDivisor(this.mode)/this.rows}px` this.container.appendChild(div) } }}this.pushOne = function (data) { for (let i = 0; i < this.rows; i++) { if (!this.list[i]) this.list[i] = [] } let leastRow = getLeastRow(this.list) //获取弹幕列表中最少的那一列,弹幕列表是一个二维数组 this.list[leastRow].push(data)}this.pushArr = function (data) { let list = sliceRowList(this.rows, data) list.forEach((item, index) => { if (this.list[index]) { this.list[index] = this.list[index].concat(...item) } else { this.list[index] = item } })}//根据行数把一维的弹幕list切分成rows行的二维数组function sliceRowList(rows, list) { let sliceList = [], perNum = Math.round(list.length / rows) for (let i = 0; i < rows; i++) { let arr = [] if (i == rows - 1) { arr = list.slice(i * perNum) } else { i == 0 ? arr = list.slice(0, perNum) : arr = list.slice(i * perNum, (i + 1) * perNum) } sliceList.push(arr) } return sliceList}

持续加入数据的方法只是调用了添加源数据的方法,并且开始了调度而已

this.addData = function (data) { this.pushData(data) this.start()}

发射弹幕

下面来看看发射弹幕的逻辑

this.start = function () { //开始调度list this.dispatchList(this.list)}this.dispatchList = function (list) { for (let i = 0; i < list.length; i++) { this.dispatchRow(list[i], i) }}this.dispatchRow = function (row, i) { if (!this.indexs[i] && this.indexs[i] !== 0) { this.indexs[i] = 0 } //真正的调度从这里开始,用一个实例变量存储好当前调度的下标。 if (row[this.indexs[i]]) { this.dispatchItem(row[this.indexs[i]], i, this.indexs[i]) }}

this.dispatchItem = function (item, i) { //调度过一次的某条弹幕下一次在调度就不需要了 if (!item || this.idMap[item.id]) { return } let index = this.indexs[i] this.idMap[item.id] = item.id let div = document.createElement('div'), parent = document.querySelector(`${el} .barrage-list-${i}`), width, pastTime div.innerHTML = item.content div.className = 'barrage-item' parent.appendChild(div) width = getBoxSize(div).width div.style = `width:${width}px;display:none` pastTime = this.computeTime(width) //计算出下一条弹幕应该出现的时间 //弹幕飞一会~ this.run(div) if (index > this.list[i].length - 1) { return } let len = this.timeoutFuncs.length //记录好定时器,后面清空 this.timeoutFuncs[len] = setTimeout(() => { this.indexs[i] = index + 1 //递归调用下一条 this.dispatchItem(this.list[i][index + 1], i, index + 1) }, pastTime);}

//用css动画,整体还是比较流畅的this.run = function (item) { item.classList += ' running' item.style.left = "left:100%" item.style.display = '' item.style.animation = `run ${this.speed/1000}s linear` //已完成的打一个标记 setTimeout(() => { item.classList+=' done' }, this.speed);}//根据弹幕的宽度和gapWth,算出下一条弹幕应该出现的时间this.computeTime = function (width) { let length = width + this.gapWidth let time = Math.round(length / this.boxSize.width * this.speed/2) return time}

动画css具体如下

@keyframes run { 0% { left: 100%; } 50% { left: 0 } 100% { left: -100%; }}.run { animation-name: run;}

其余方法

停止

利用动画的paused属性停止

this.stop = function () { let items = document.querySelectorAll(`${el} .barrage-item`); [...items].forEach(item => { item.className += ' pause' })}

.pause { animation-play-state: paused !important;}

重新开始

移除pause类即可

this.restart = function () { let items = document.querySelectorAll(`${el} .barrage-item`); [...items].forEach(item => { removeClassName(item, 'pause') })}

打开关闭

做一个显示隐藏的逻辑即可

this.close = function () { this.container.style.display = 'none'}this.open = function () { this.container.style.display = ''}

清理弹幕

this.clearData = function () { //清除list this.list = [] //清除dom document.querySelector(`${el}`).innerHTML = '' //清除timeout this.timeoutFuncs.forEach(fun => clearTimeout(fun))}

最后用一个定时器定时清理过期的弹幕:

setInterval(() => { let items = document.querySelectorAll(`${el} .done`); [...items].forEach(item=>{ item.parentNode.removeChild(item) })}, this.speed*5);

最后

感觉这个的实现还是有缺陷的,如果是你设计这么一个类,你会怎么设计呢?

到此这篇关于原生JavaScript实现弹幕组件的示例代码的文章就介绍到这了,更多相关JavaScript 弹幕组件内容请搜索真格学网以前的文章或继续浏览下面的相关文章希望大家以后多多支持真格学网!  您可能感兴趣的文章:js实现弹幕飞机效果javascript实现视频弹幕效果(两个版本)javascript实现弹幕墙效果利用JS代码自动删除稿件的普通弹幕功能JS实现的视频弹幕效果示例基于JavaScript实现弹幕特效简单实现JavaScript弹幕效果JavaScript直播评论发弹幕切图功能点集合效果代码

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html> <head>  <title>javascript弹幕2113</title>  <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />     <style>        #play{            width:600px;            height:500px;            background-color:#000;        }                 #tangmu{            width:600px;            height:500px;            background-color:#fff;            z-index:9999;            background-color: rgba(000, 1, 000, 0.1);         }                 #textStyle{            position:absolute;            font-size:24px;            color:#fff;        }    </style>      </head>  <body>    <div id="play">        <div id="tangmu">                     </div>    </div>         <input type="text" id="text" value="这是5261弹4102幕..."/><input type="button" value="发送1653" onClick="tangmu();"/>         <script>        var si;        function tangmu(){            clearInterval(si);            var text = document.getElementById("text");            var tangmu = document.getElementById("tangmu");             var textStyle="<font id=\"textStyle\">"+text.value+"</font>";                         mathHeight = Math.round(Math.random()*tangmu.offsetHeight)+"px";             var textLeft=tangmu.offsetWidth+"px";                         tangmu.innerHTML=textStyle;                         var textStyleObj = document.getElementById("textStyle");                         textStyleObj.style.left=textLeft;            textStyleObj.style.top=mathHeight;                         var x=parseInt(textStyleObj.style.left);                         si = setInterval("xunhuan("+x+")",100);                     }        function xunhuan(left){            var textStyleObj = document.getElementById("textStyle");            textStyleObj.style.left=left;                         var x=parseInt(textStyleObj.style.left);             if(x<textStyleObj.style.width){                document.getElementById("tangmu").innerHTML="";                clearInterval(si);            }else{                x-=18;            }                         textStyleObj.style.left=x+"px";        }    </script>      </body></html>内容来自www.zgxue.com请勿采集。


  • 本文相关:
  • js在输入框屏蔽按键,只能键入数字的示例代码
  • js canvas画布实现高斯模糊效果
  • javascript编程之继承实例汇总
  • js获取下拉框选定项的值和文本的实现代码
  • js实现无缝轮播图特效
  • js实现的合并多个数组去重算法示例
  • javascript 删除确认实现方法小结
  • js实现的几个常用算法
  • 微信小程序实现录音时的麦克风动画效果实例
  • javascript定义变量和变量优先级问题探讨
  • 如何用javascript代码实现弹幕效果
  • 小说中的弹幕怎么实现的,是JavaScript和css3? 最...
  • 如何用javascript写弹幕播放器的弹幕时间轴触发器
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全基础知识javascript类库表单特效广告代码网页特效黑客性质javascript技巧domnode.jsjs其它首页javascriptjs实现弹幕飞机效果javascript实现视频弹幕效果(两个版本)javascript实现弹幕墙效果利用js代码自动删除稿件的普通弹幕功能js实现的视频弹幕效果示例基于javascript实现弹幕特效简单实现javascript弹幕效果javascript直播评论发弹幕切图功能点集合效果代码js在输入框屏蔽按键,只能键入数字的示例代码js canvas画布实现高斯模糊效果javascript编程之继承实例汇总js获取下拉框选定项的值和文本的实现代码js实现无缝轮播图特效js实现的合并多个数组去重算法示例javascript 删除确认实现方法小结js实现的几个常用算法微信小程序实现录音时的麦克风动画效果实例javascript定义变量和变量优先级问题探讨js刷新页面方法大全js中settimeout()的用法详解js截取字符串常用方法详细整理js页面跳转常用的几种方式js删除数组里的某个元素方法js打开新窗口的2种方式js数组与字符串的相互转换方法js设置cookie、读取cookie、删除js 将json字符串转换为json对象的js关闭当前页面(窗口)的几种方式javascript 区别浏览器 代码javascript基本常用排序算法解析javascript 尚未实现错误解决办法javascript数组去重算法实例小结详解javascript数组和字符串中去除重复值javascript 获取鼠标的绝对位置 eventjs实现页面打印(整体、局部)javascript中的方法和匿名方法实例详解javascript实现简单的富文本编辑器附演示
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved