> 웹 프론트엔드 > JS 튜토리얼 > 기본 JavaScript에서 사격 구성 요소를 구현하는 방법

기본 JavaScript에서 사격 구성 요소를 구현하는 방법

coldplay.xixi
풀어 주다: 2020-10-09 16:32:29
앞으로
2309명이 탐색했습니다.

오늘

JavaScript 칼럼에서는 기본 JavaScript를 사용하여 Barrage 구성 요소를 구현하는 방법을 소개합니다.

기본 JavaScript에서 사격 구성 요소를 구현하는 방법

Preface

요즘에는 거의 모든 비디오 웹사이트에 사격 기능이 있으므로 오늘은 네이티브 JavaScript를 사용하여 사격 클래스를 캡슐화하겠습니다. 이 클래스는 다음과 같은 속성과 인스턴스 메소드를 갖고 싶어합니다: 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 = []
}复制代码
로그인 후 복사

先接受好参数然后初始化,下面看看getBoxSizeinitRows

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 컨테이너 노드에 대한 선택기, 컨테이너 노드는 다음과 같아야 합니다. 절대 위치 및 너비와 높이 설정
  • height 각 포격의 높이
  • mode 포격 모드에서는 절반이 절반입니다 컨테이너 높이, 상단은 1/3, 가득 참
  • 속도탄격이 화면을 가로지르는 데 걸리는 시간
  • gapWidth</code >다음 글머리 기호와 이전 글머리 기호 사이의 거리</li></ul><h2 data-id="heading-2">방법 <p><ul><li><code>pushData</code > 글머리 기호 화면 메타데이터 추가</li><li><code>addData연속 사격 추가
  • start공격 예약 시작
  • < code >stop포격 중지
  • restart 포격 다시 시작
  • clearData포격 취소
  • 닫기닫기
  • 열기포격 다시 표시

PS: 자체 캡슐화된 도구 기능이 있습니다. 여기에 올리지는 않겠지만 무슨 뜻인지는 아마 아실 겁니다

초기화

자바스크립트 파일을 소개한 후 아래와 같이 사용하려고 합니다. 먼저 기본값을 채택합니다. 구성.

function 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 &#39;half&#39;:
            pisor = .5
            break
        case &#39;top&#39;:
            pisor = 1 / 3
            break;        case &#39;full&#39;:
            pisor = 1;            break
        default:            break;
    }    return pisor
}复制代码
로그인 후 복사

매개변수 초기화:

this.pushData = function (data) {    this.initDom()    if (getType(data) == &#39;[object Object]&#39;) {        //插入单条
        this.pushOne(data)
    }    if (getType(data) == &#39;[object Array]&#39;) {        //插入多条
        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(&#39;p&#39;)
            p.classList = `barrage-list barrage-list-${i}`
            p.style.height = `${this.boxSize.height*getpisor(this.mode)/this.rows}px`
            this.container.appendChild(p)
        }
    }
}复制代码
로그인 후 복사

매개변수를 먼저 승인한 후 초기화하세요. getCompulatedStyle을 통해 계산된 <code>getBoxSizeinitRows

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
}复制代码
로그인 후 복사

를 살펴보겠습니다. api 상자의 너비와 높이는 나중에 사용되는 컨테이너의 너비와 높이를 계산하는 데 사용됩니다.

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 p = document.createElement(&#39;p&#39;),
        parent = document.querySelector(`${el} .barrage-list-${i}`),
        width,
        pastTime
    p.innerHTML = item.content
    p.className = &#39;barrage-item&#39;
    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 += &#39; running&#39;
    item.style.left = "left:100%"
    item.style.display = &#39;&#39;
    item.style.animation = `run ${this.speed/1000}s linear`
    //已完成的打一个标记
    setTimeout(() => {
        item.classList+=&#39; done&#39;
    }, 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 += &#39; pause&#39;
    })
}复制代码
로그인 후 복사
.pause {    animation-play-state: paused !important;
}复制代码
로그인 후 복사

애니메이션 CSS는 다음과 같습니다

this.restart = function () {    let items = document.querySelectorAll(`${el} .barrage-item`);
    [...items].forEach(item => {
        removeClassName(item, &#39;pause&#39;)
    })
}复制代码
로그인 후 복사

나머지 방법

Stop

멈추려면 애니메이션의 Paused 속성을 사용하세요

this.close = function () {    this.container.style.display = &#39;none&#39;}this.open = function () {    this.container.style.display = &#39;&#39;}复制代码
로그인 후 복사
this.clearData = function () {    //清除list
    this.list = []    //清除dom
    document.querySelector(`${el}`).innerHTML = &#39;&#39;
    //清除timeout
    this.timeoutFuncs.forEach(fun => clearTimeout(fun))
}复制代码
로그인 후 복사

다시 시작

pause 클래스만 삭제하세요

setInterval(() => {    let items = document.querySelectorAll(`${el} .done`);
    [...items].forEach(item=>{
        item.parentNode.removeChild(item)
    })
}, this.speed*5);复制代码
로그인 후 복사
열고 닫으세요 보이지 않는 논리를 만드세요 rrreee막대를 정리하세요rrreee마지막으로 타이머를 사용하여 만료된 막사를 정기적으로 정리하세요.rrreee마지막으로🎜이 구현이 여전히 결함이 있다고 생각합니다. 이런 수업, 어떻게 디자인하시겠습니까? 🎜🎜🎜🎜관련 무료 학습 권장사항: 🎜🎜🎜javascript🎜🎜🎜(동영상)🎜🎜🎜

위 내용은 기본 JavaScript에서 사격 구성 요소를 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:juejin.im
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿