easy-barrage
Simple implementation of a barrage library
background
The text content is displayed on the page in the form of bullet curtain wall, which requires infinite loop scrolling. After searching on the Internet, I couldn't find a library that met my needs, so I implemented it myself. Tips: The implementation of this library is relatively simple, for specific needs, need to expand on this basis, or issue, learn together, common progress.Copy the code
Basic Implementation Principles
1. Calculate the number of lines of the barrage according to the height of each barrage and the height of the barrage display area (called runway) laneCount 2. Define the state map of a runway, laneStatus, to indicate the current state of the runway in idle (true) or occupied (false) 3 Storage of barrage data; ItemStatusMap is used to indicate that the current state of the barrage is in display (true) or not in display (false). 4. Cycle the runway (laneStatus) every one second. If you have idle runway again from barrage array (data) to retrieve a data begin to render, from the barrage display area into 5 to the right, in the barrage began to enter barrage display area, the runway status set to false, after completely into the barrage display area, the runway status set to true 6, roll out completely in the barrage barrage display area, Delete the DOM node of the barrage and set the state of the barrage to falseCopy the code
Attach a effect
Method of use
Copy the barrage. Js file from the SRC directory (the barrage. Js file from the dist directory is packaged) and import it as import.
import Barrage from '.. /src/barrage'
import { barrageData } from './data'
const el = document.getElementsByClassName('container')[0] Const barrage = new Barrage({barrage: el, // 26, // Mandatory height unit px speed: 3, // The speed parameter ranges from 1 to 5. The higher the speed, the faster the speed. The default value is 3.trueInfinite is not displayed by default:true}) barrage.init()Copy the code
Attached main source code
class Barrage {
constructor (options) {
const data = Object.assign({}, {
data: [],
barrageHeight: 26,
speed: 3,
showAvatar: false,
infinite: false}, Container this.data = data.data // Projectile state mapping this.itemStatusMap = new Array(this.data.length).fill(true)
this.itemHeight = data.barrageHeight
this.speed = data.speed * 0.0293
this.showAvatar = data.showAvatar
this.infinite = data.infinite
}
init() {// Initialize barrage runway this.initlane () // Initialize barrage runway this.inittimer ()}initTimer () {
if (this.data.length > 0) {
this.timer = setInterval(() => {
for (leti = 0; i < this.laneCount; I++) {const lane = this.getlane () const pointer = this.getonebarrage (if(pointer === -1 && ! this.infinite) { clearInterval(this.timer)return
}
if (lane > -1 && pointer > -1) {
this.laneStatus[lane] = false
this.initItemDom(pointer, lane)
this.itemStatusMap[pointer] = false
}
}
}, 1000)
}
}
initItemDom (pointer, lane) {
const data = this.data[pointer]
const el = document.createElement('div')
el.classList.add('barrage')
const startLeft = this.containerWidth + Math.floor(Math.random() * 50)
const top = lane * this.itemHeight + lane * this.gap
el.style = `top: ${top}px; left: ${ startLeft }px; height: ${this.itemHeight}px; border-radius:${this.itemHeight / 2}px`
el.innerHTML = `${this.showAvatar ? '<img class="avatar" src="' + data.avatar + '"/>' : ''}
<p class="content">${data.text}</p>`
this.container.appendChild(el)
const width = el.offsetWidth
const animateTime = Math.ceil((width + startLeft) / this.speed)
this.animate(el, startLeft, -width, animateTime, () => {
if (this.infinite) {
this.itemStatusMap[pointer] = true
}
el.remove()
})
const inScreenTime = animateTime / (width + this.containerWidth) * width
setTimeout(() => {
this.laneStatus[lane] = true
}, inScreenTime)
}
initLane () {
this.containerWidth = this.container.clientWidth
this.containerHeight = this.container.clientHeight
this.laneCount = Math.floor(this.containerHeight / this.itemHeight)
this.laneStatus = new Array(this.laneCount).fill(trueThis.gap = math.floor (this.containerheight % this.itemheight/(this.lanecount-1))}getLane () {
let lane = Math.floor(Math.random() * this.laneCount)
let times = 1
while (times < this.laneCount) {
if (this.laneStatus[lane]) {
return lane
} else {
lane === this.laneCount - 1 ? lane = 0 : lane++
times+ +}}return1}getOneBarrage () {
returnthis.itemStatusMap.findIndex(item => item) } animate (el, start, des, duration, Const createTime = () => +new Date() const startTime = createTime()function tick() { const remaining = Math.max(0, StartTime + duration - createTime ()) const temp = remaining/duration | | 0 const percent = 1 - temp / / in the end each moving distance of the left const leftPos = (des - start) * percent + startif (1 === percent) {
window.cancelAnimationFrame(frameId)
el.style.left = des + 'px'
callback()
} else {
el.style.left = leftPos + 'px'Window. RequestAnimationFrame (tick)}} / / start animation const frameId = window. RequestAnimationFrame (tick)} _isDom (el) {return el && typeof el === 'object' && el.nodeType === 1 && typeof el.nodeName === 'string'
}
_checkSpeed (speed) {
return speed % 1 === 0 && speed >=1 && speed <= 5
}
}
export default Barrage
Copy the code