Commit 1dbb624a by qiuren

feat:新增弹幕滚动库

parent 1a9ac6e4
Showing with 248 additions and 0 deletions
// 弹幕滚动库
!function(t, e) {
"object" == typeof exports && "undefined" != typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define(e) : (t = "undefined" != typeof globalThis ? globalThis : t || self).BulletJs = e()
}(this, (function() {
"use strict";
const t = "__bullet-item-style"
, e = "__bullet-temp-container";
function i(t, e, i, s) {
t.addEventListener(e, (e => {
let n = e.target;
for (; !n.className.includes(i); ) {
if (n === t) {
n = null;
break
}
n = n.parentNode
}
n && s(n)
}
))
}
var remBase = parseFloat(getComputedStyle(document.documentElement).fontSize);
const s = {
trackHeight: 50,
pauseOnHover: !1,
pauseOnClick: !1,
onStart: null,
onEnd: null,
duration: "10s",
trackArr: [{
speed: 150
}, {
speed: 130
}],
speed: 100
};
return class {
ele;
options;
targetPos;
target = null;
tempContanier = null;
bulletInfo = {
width: 0
};
bullets = [];
tracks = [];
queues = [];
targetW = 0;
pauseArrs = [];
isAllPaused = !1;
constructor(t, e={}) {
this.options = Object.assign(s, e),
this.ele = t,
this.initScreen(),
this.initOpt(),
this.initTempContainer(),
this._addExtraEvent()
}
initScreen() {
if ("string" == typeof this.ele) {
if (this.target = document.querySelector(this.ele),
!this.target)
throw new Error("The display target does not exist")
} else {
if (!(this.ele instanceof HTMLElement))
throw new Error("The display target of the barrage must be set");
this.target = this.ele
}
}
initOpt() {
const {trackHeight: i} = this.options;
this.targetPos = this.target.getBoundingClientRect();
const s = Math.floor(this.targetPos.height / i);
this.tracks = new Array(s).fill("idle"),
this.bullets = new Array(s).fill([]),
this.targetW = this.targetPos.width;
const {position: n} = getComputedStyle(this.target);
"static" === n && (this.target.style.position = "relative",
this.target.style.overflow = "hidden"),
(i => {
let s = document.createElement("style");
s.classList.add("BULLET_ANIMATE");
const n = `@keyframes RightToLeft { from { visibility: visible; transform: translateX(${i}px); } to { visibility: visible; transform: translateX(-100%); } }`
, a = `\n .${t} {\n\t\tcursor: pointer;\n\t\tposition: absolute;\n\t\tleft: 0;\n\t\tanimation-name: RightToLeft;\n\t\tanimation-timing-function: linear;\n\t\toverflow: hidden;\n\t\tdisplay: inline-block;\n\t\tword-break: keep-all;\n\t\twhite-space: nowrap;\n\t}`
, r = `\n\t.${e} {\n\t\tposition: absolute;\n\t\tright: 9999px;\n\t\tvisibility: hidden;\n\t}`;
s.innerHTML = n + a + r,
document.head.appendChild(s)
}
)(this.targetW)
}
initTempContainer() {
this.tempContanier = document.createElement("div"),
this.tempContanier.classList.add(e),
document.body.appendChild(this.tempContanier)
}
push(t, e={}, i=!1) {
if (this.isAllPaused)
return;
const s = Object.assign({}, this.options, e)
, n = this._getTrackIndex();
if (-1 !== n) {
const e = this._getBulletItem(t, s, n);
return this.bullets[n].length ? this.bullets[n].push(e) : this.bullets[n] = [e],
this._render(e, n),
this._addEvent(e, n, s),
e.id
}
i && this.queues.push({
item: t,
opts: e
})
}
_getBulletItem(e, i, s) {
const n = ( () => {
const e = document.createElement("div");
return e.id = Math.random().toString(36).substring(2),
e.classList.add(t),
e
}
)();
n.innerHTML = e,
this.tempContanier.innerHTML = "",
this.tempContanier.appendChild(n),
this.bulletInfo = {
width: n.offsetWidth
};
let a = 0;
const r = i.trackArr?.[s]?.speed || i.speed;
return a = r ? (this.targetW + this.bulletInfo.width) / r : +i.duration.slice(0, -1),
n.dataset.duration = a + "",
n.style.animationDuration = 1e3 * a + "ms",
n.remove(),
n
}
_getTrackIndex() {
let t = []
, e = -1;
if (this.tracks.forEach(( (e, i) => "idle" === e && t.push(i))),
t.length) {
const n = (i = 0,
s = t.length - 1,
parseInt(Math.random() * (s - i + 1)) + i);
return e = t[n],
this.tracks[e] = "running",
e
}
var i, s;
for (let t = 0; t < this.bullets.length; t++) {
const e = this.bullets[t].length;
if (e) {
const i = this.bullets[t][e - 1];
if (i && this._checkTrack(i))
return t
}
}
return e
}
_checkTrack(t) {
const e = t.getBoundingClientRect();
if (e.right > this.targetPos.right)
return !1;
if (this.options.speed || this.options.trackArr?.length) {
if (e.right < this.targetPos.right)
return !0
} else {
const i = +t.dataset.duration
, s = (this.targetW + e.width) / i
, n = (this.targetW + this.bulletInfo.width) / i;
if (n <= s)
return !0;
{
const t = (e.right - this.targetPos.left) / s;
if (this.targetW / n < t)
return !1
}
}
return !0
}
_addEvent(t, e, i) {
const {onStart: s, onEnd: n} = i;
t.addEventListener("animationstart", ( () => {
s && s.call(window, t.id, this)
}
)),
t.addEventListener("animationend", ( () => {
n && n.call(window, t.id, this),
this.bullets[e] = this.bullets[e].filter((e => e.id !== t.id)),
this.bullets[e].length || (this.tracks[e] = "idle"),
t.style.willChange = "auto",
t.remove()
}
))
}
_addExtraEvent() {
this.options.pauseOnClick && i(this.target, "click", t, (t => {
"paused" == t.style.animationPlayState && t.dataset.clicked ? (t.dataset.clicked = "",
this._toggleAnimateStatus(t, "running")) : (t.dataset.clicked = "true",
this._toggleAnimateStatus(t, "paused"))
}
)),
this.options.pauseOnHover && (i(this.target, "mouseover", t, (t => {
this._toggleAnimateStatus(t, "paused")
}
)),
i(this.target, "mouseout", t, (t => {
this._toggleAnimateStatus(t, "running")
}
)))
}
_render = (t, e) => {
if (!this.isAllPaused && (t.dataset.track = e + "",
t.style.top = (e * this.options.trackHeight)/remBase + "rem",
t.style.willChange = "transform",
this.target.appendChild(t),
this.queues.length)) {
const t = this.queues.shift();
this.push(t.item, t.opts, !0)
}
}
;
getBulletsList() {
return this.bullets.reduce(( (t, e) => [...e, ...t]), [])
}
_toggleAnimateStatus = (t, e="paused") => {
t ? "running" === e ? (t.style.animationPlayState = "running",
t.style.zIndex = "0",
t.classList.remove("bullet-item-paused")) : (t.style.animationPlayState = "paused",
t.style.zIndex = "99999",
t.classList.add("bullet-item-paused")) : this.pauseArrs.length && "paused" == e || (this.pauseArrs = this.getBulletsList(),
this.pauseArrs.forEach((t => {
t.style.animationPlayState = e
}
)),
this.pauseArrs = [])
}
;
pause(t=null) {
this._toggleAnimateStatus(t, "paused"),
null === t && (this.isAllPaused = !0)
}
resume(t=null) {
this._toggleAnimateStatus(t, "running"),
this.isAllPaused = !1
}
}
}
));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment