基于原生js实现主流弹幕的所有功能

原生js实现弹幕效果原理 二 距离写实现原理一有很长一段时间了,因为好像没什么人看,所以我就不太想写原理二,为了不食言,我还是坚持做完这个系列吧

下面介绍的就是目前主流直播弹幕网站的弹幕实现方式,包括弹幕指定暂停,点赞,举报功能.

首先来看一张实现动图
barrage-2 原理简介
  • 动画效果使用css3中的 transition 属性实现
  • 只有transition是远远不够的,因为transition需要主动触发,但是一般网上常见的简单的触发方式,就是 定义css样式的:hover或者:focus属性,指定用户的某一个活动主动触发transition,这显然是无法实现弹幕自动化效果的。因此,可以想到使用js触发。css触发说到底也就是当满足某种条件时,替换dom元素的class样式。
  • 知道原理以后我们要做的就是,在适当的时机给弹幕dom添加上class或者移除class,在js里这是非常简单的,dom.classList.add("xxx")实现添加class,dom.classList.remove("xxx")移除class.
  • 上面强调的 适当 这个词大有文章,众所周知,js是一个单线程编程语言,可能有些人被setInterval和setTimeOut函数误导,以为是js引擎新开了一个线程去处理定时功能,但实际上,js引擎所做仅仅只是,1.将计时任务放到一个带有优先级的事件队列中 2.然后一个一个的执行事件
  • 上面说了js引擎是单线程按队列顺序执行事件,但每个事件之间不可避免的会有间隔时间,在这个间隔时间里js引擎是空闲的,当js引擎空闲时,就是GUI绘制引擎工作的时间了,GUI引擎做的工作就是渲染dom。即是说,并不是说js刚改变class,dom元素的样式就会刷新,中间有一个间隔时间,这个间隔时间就是GUI引擎在等待js引擎空闲,具体的细节你们可以去https://blog.csdn.net/qq_36995542/article/details/80007381看看。当初我把我对js单线程的理解发到一个前端群的时候,有个25仔说这已经达到了月薪2万的前端水准,老子信了他的鬼。。。。
源代码解析 首先是html
------------- - 锐客网 测试弹幕.....基于原生js实现主流弹幕的所有功能
文章图片
0 黑色 红色 绿色 白色

我实在是不知道怎么让html代码在不被解析的情况下保持缩进...
html代码没什么好说的,连这个都看不懂的话,下面的基本也没戏了。
重头戏js源码
  • js这门语言的特点就是: 它的语义宽松,这也就导致了很多的js代码写出来显得杂乱无章,比如我这个。但是用熟练了以后,你就会发现它越用越上瘾。
?
"use strict";
var barrageContent = document.getElementsByClassName("barrage-content")[0]; // var rect = barrageContent.getBoundingClientRect(); /** * 弹道 * @type {HTMLCollectionOf} */ var barrageRoad = document.getElementsByClassName("barrage-road"); var rangeValue = https://www.it610.com/article/20; //字体大小 预设值var sliderHandle = document.getElementsByClassName("range-slider-handle")[0]; //字体调节滑块 var slider = document.getElementsByClassName("range-slider")[0]; var sliderRect = slider.getBoundingClientRect(); var sliderFill = document.getElementsByClassName("range-slider-fill")[0]; //滑过区域 var textPreview = document.getElementsByClassName("text-preview")[0]; //预览字体区var content = document.getElementsByClassName("comment-input")[0]; //弹幕输入框 var speedNum = document.getElementsByClassName("speed-selector")[0]; //弹幕速度 var color = document.getElementsByName("colorSelected"); //弹幕颜色选择器 var colorSelected = "white"; //被选择颜色 预设值var transitionEvent = whichTransitionEvent(); //判断浏览器内核类型var index = 1; //数据库弹幕表分页页码var deviceType = goPAGE(); var I = 0; //右键弹幕的id sliderHandle.style.left = "0px"; /** * 测试用数据 数据格式,我下面的源码获取数据是用的我自己建的后台,如果你只是想要一个单机版的话,直接添加下面数组里的初始化数据就行,每个字段都要。 * @type {*[]} */ var barrageData_2 = [ { "barrageId": 1, "content": "第二条弹幕.............", "color": "red", "speed": 16, "textSize": 20, "road": 0, "starNum":0 } ]; barrageData_2 = barrageData_2.concat(); /** * 初始化操作自执行函数 */ (function () { for (var i = 0; i < barrageData_2.length; i++) { barrageData_2[i]["road"] = i % barrageRoad.length; } console.log("screen-size", screen.width, screen.height); var that = this; var timer = setInterval(function (args) { if (barrageData_2.length <= 0) { console.log("barrageData:", barrageData_2); regularGetBarrage(); return; } sendBarrage(barrageData_2[0]["barrageId"], barrageData_2[0]["content"], barrageData_2[0]["color"], barrageData_2[0]["speed"], barrageData_2[0]["textSize"], barrageData_2[0]["road"]); barrageData_2.splice(0, 1); }, 1000); })(); window.onload = function (ev) { document.getElementsByClassName("menu-item")[0].onclick = report; //TODO }/** * 鼠标指定弹幕事件函数 * @param event */ function onMouseIn(event) { var barrage = event.valueOf(); var computeStyle = window.getComputedStyle(barrage), left = computeStyle.getPropertyValue("left"); barrage.style.left = left; barrage.classList.remove("barrage-active"); }/** * 鼠标离开弹幕事件函数 * @param event */ function onMouseLeave(event) { var barrage = event.valueOf(); barrage.classList.add("barrage-active"); }/** * 弹幕点击事件 * @param event */ function mouseClicked(event) { var barrage = event.valueOf(); barrage.classList.add("barrage-clicked"); barrage.childNodes[1].setAttribute("src", "/pic/star-active.png"); barrage.childNodes[3].innerHTML = parseInt(barrage.childNodes[3].innerHTML) + 1; star(barrage); }/** * 弹幕发送处理函数 * @param index * @param content 弹幕内容 * @param colorSelected 选择的颜色 * @param speedNum 弹幕速度 * @param rangeValue 字体大小 * @param roadNum 弹道 */ function sendBarrage(barrageId, content, colorSelected, speedNum, rangeValue, roadNum) {var newBarrage = document.createElement("span"); if (content === "") { return; }newBarrage.classList.add("barrage"); newBarrage.style.setProperty("color", colorSelected); newBarrage.style.transitionDuration = speedNum + "s"; newBarrage.style.webkitTransitionDuration = speedNum + "s"; newBarrage.style.setProperty("font-size", rangeValue + "px"); newBarrage.innerHTML = content + "基于原生js实现主流弹幕的所有功能" + ""+barrageData_2[0]["starNum"]+""; newBarrage.onmouseenter = function (ev) { onMouseIn(this); }; newBarrage.onmouseleave = function (ev) { onMouseLeave(this); }; if (deviceType === "pc"){ newBarrage.onclick = function (ev) { var ul = document.getElementsByClassName("right-menu-ul")[0]; ul.style.display = "none"; mouseClicked(this); }; } else { newBarrage.ontouchend = function (ev) { var ul = document.getElementsByClassName("right-menu-ul")[0]; ul.style.display = "none"; mouseClicked(this); } }newBarrage.oncontextmenu = function (ev) { var ul = document.getElementsByClassName("right-menu-ul")[0]; // console.log("contextmenu", ev.currentTarget.valueOf().childNodes); event.preventDefault(); //TODO 奇迹的用法 I = barrageId; ul.style.display = "block"; ul.style.left = event.clientX + 10 + "px"; ul.style.top = event.clientY + 10 + "px"; }; //TODO 备注,dom初始化的时机 barrageRoad[roadNum].appendChild(newBarrage); setTimeout(function () { newBarrage.classList.add("barrage-active"); },50); newBarrage.addEventListener(transitionEvent, function (evt) { // console.log(this); this.parentNode.removeChild(this); // barrageData_2.splice(0, 1); console.log("----------------------transitionEnd事件触发一次---------------"); }); }/** * 滑块鼠标按下事件函数 * @param event */ if (deviceType === "pc"){ sliderHandle.onmousedown = function (event) { var that = this; var oldX = event.clientX; var left = parseInt(that.style.left); document.onmousemove = function (ev) { var x = ev.clientX - oldX; that.style.left = left + x + "px"; rangeValue = https://www.it610.com/article/Math.ceil((parseInt(that.style.left) / sliderRect.width) * 40) + 1; if (parseInt(that.style.left) < 0) { that.style.left ="0"; rangeValue = https://www.it610.com/article/10; } if (parseInt(that.style.left)> sliderRect.width) { that.style.left = sliderRect.width - 10 + "px"; rangeValue = https://www.it610.com/article/50; } sliderFill.style.width = that.style.left; textPreview.style.fontSize = rangeValue +"px"; console.log("rangeValue: ", rangeValue); }; document.onmouseup = function (ev) { document.onmouseup = null; document.onmousemove = null; } }; } else { sliderHandle.ontouchstart = function (event) { var that = this; var oldX = event.clientX; var left = parseInt(that.style.left); document.ontouchmove = function (ev) { var x = ev.clientX - oldX; that.style.left = left + x + "px"; console.log("left", that.style.left); rangeValue = https://www.it610.com/article/Math.ceil((parseInt(that.style.left) / sliderRect.width) * 40) + 1; if (parseInt(that.style.left) < 0) { that.style.left ="0"; rangeValue = https://www.it610.com/article/10; } if (parseInt(that.style.left)> sliderRect.width) { that.style.left = sliderRect.width - 10 + "px"; rangeValue = https://www.it610.com/article/50; } sliderFill.style.width = that.style.left; textPreview.style.fontSize = rangeValue +"px"; console.log("rangeValue: ", rangeValue); }; document.ontouchend = function (ev) { document.ontouchend = null; document.ontouchmove = null; } }; }/** * 发送弹幕按钮点击事件响应函数 */ function addBarrageData() { var item = { "content": "", "color": "red", "speed": 16, "textSize": 20, "road": 0, "starNum": 0 }; var content_1 = content.value; item["speed"] = speedNum.value; item["textSize"] = rangeValue; item["road"] = Math.floor(Math.random() * barrageRoad.length); content_1 = contentFilter(); item["content"] = content_1; console.log("content: ", content_1); for (var i = 0; i.*?<\/.*?>/g, '[非法字段]'); content_1 = content_1.replace(/
css代码
【基于原生js实现主流弹幕的所有功能】这个我就放github上算了,不然篇幅实在是太长了。
https://github.com/TomShiDi/barrage-website
下一篇文章预告
实现一个基于springboot框架的注解方法跟踪小框架

    推荐阅读