Heim >Web-Frontend >js-Tutorial >So implementieren Sie die Barrage-Komponente in nativem JavaScript
In der Kolumne „
JavaScript“ wird heute vorgestellt, wie Barrage-Komponenten mit nativem JavaScript implementiert werden.
Heutzutage verfügen fast alle Video-Websites über die Barrage-Funktion, daher werden wir heute natives JavaScript
verwenden, um eine Barrage-Klasse zu kapseln. Diese Klasse hofft, über die folgenden Attribute und Instanzmethoden zu verfügen: 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'))) } }复制代码
通过getComputedStyle
el
Selektor für Containerknoten, Containerknoten sollten sein absolute Position, legen Sie die Breite und Höhe festheight
Die Höhe jedes Sperrfeuersmode
Sperrmodus, halb ist halb Die Die Höhe des Behälters beträgt ein Drittel, und „full“ ist vollspeed
Die Zeit, die das Sperrfeuer braucht, um den Bildschirm zu überquerengapWidth
Der Abstand zwischen dem nächsten Aufzählungszeichen und dem vorherigen AufzählungszeichenpushData
Aufzählungsbildschirm-Metadaten hinzufügenaddData
Barrage kontinuierlich hinzufügenstart
Planung von Barrage starten stop
Stoppen Sie das Sperrfeuerrestart
Starten Sie das Sperrfeuer erneutclearData
Löschen Sie das Sperrfeuerschließen
Schließenöffnen
Anzeigen Sie die Sperre erneutfunction initRows(box, mode, height) { let pisor = getpisor(mode) rows = Math.ceil(box.height * pisor / height) return rows }function getpisor(mode) { let pisor = .5 switch (mode) { case 'half': pisor = .5 break case 'top': pisor = 1 / 3 break; case 'full': pisor = 1; break default: break; } return pisor }复制代码
Parameterinitialisierung:
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 p = document.createElement('p') p.classList = `barrage-list barrage-list-${i}` p.style.height = `${this.boxSize.height*getpisor(this.mode)/this.rows}px` this.container.appendChild(p) } } }复制代码
Akzeptieren Sie zuerst die Parameter und initialisieren Sie sie dann. Werfen wir einen Blick auf getBoxSize
und initRows
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 }复制代码
getComputedStyle
api Aus der Breite und Höhe der Box werden die Breite und Höhe des Containers berechnet, die später auch verwendet werden. this.addData = function (data) { this.pushData(data) this.start() }复制代码
Berechnen Sie anhand der Höhe, wie viele Linien das Sperrwerk haben sollte. Die Anzahl der Linien wird irgendwo unten verwendet.
Daten einfügen
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 p = document.createElement('p'), parent = document.querySelector(`${el} .barrage-list-${i}`), width, pastTime p.innerHTML = item.content p.className = 'barrage-item' parent.appendChild(p) width = getBoxSize(p).width p.style = `width:${width}px;display:none` pastTime = this.computeTime(width) //计算出下一条弹幕应该出现的时间 //弹幕飞一会~ this.run(p) 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 }复制代码
@keyframes run { 0% { left: 100%; } 50% { left: 0 } 100% { left: -100%; } }.run { animation-name: run; }复制代码
this.stop = function () { let items = document.querySelectorAll(`${el} .barrage-item`); [...items].forEach(item => { item.className += ' pause' }) }复制代码
Das Animations-CSS lautet wie folgt:
.pause { animation-play-state: paused !important; }复制代码
Erstellen Sie einfach eine Show-Hide-Logik Wie würden Sie eine solche Klasse gestalten? Verwandte kostenlose Lernempfehlungen:
Javascript
(Video)Das obige ist der detaillierte Inhalt vonSo implementieren Sie die Barrage-Komponente in nativem JavaScript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!