fixed 弹幕卡顿
This commit is contained in:
1 parent
7962db84f1
commit
5d5daaa3b7
2 files changed
+68
-33
No files matched your search
@@ -2224,6 +2224,10 @@ input[type=submit] {
|
|||||||
pointer-events: none; /* 容器不阻挡点击 */
|
pointer-events: none; /* 容器不阻挡点击 */
|
||||||
z-index: 1; /* 在 main (z-index: 10) 背后,但在 body 背景之上 */
|
z-index: 1; /* 在 main (z-index: 10) 背后,但在 body 背景之上 */
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
/* 性能优化:CSS 隔离 */
|
||||||
|
contain: layout style paint;
|
||||||
|
/* 某些浏览器可能支持 content-visibility */
|
||||||
|
content-visibility: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 弹幕条目 (左到右) */
|
/* 弹幕条目 (左到右) */
|
||||||
@@ -2241,6 +2245,9 @@ input[type=submit] {
|
|||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
/* 缩小整体尺寸 */
|
/* 缩小整体尺寸 */
|
||||||
transform-origin: left top;
|
transform-origin: left top;
|
||||||
|
/* 硬件加速 */
|
||||||
|
backface-visibility: hidden;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 头像样式 */
|
/* 头像样式 */
|
||||||
|
|||||||
@@ -135,6 +135,54 @@
|
|||||||
|
|
||||||
// 追踪当前屏幕上显示的弹幕 ID
|
// 追踪当前屏幕上显示的弹幕 ID
|
||||||
this.activeIds = new Set();
|
this.activeIds = new Set();
|
||||||
|
// 最大同屏数量限制,防止卡顿
|
||||||
|
this.maxActiveItems = 30;
|
||||||
|
|
||||||
|
// 绑定事件委托
|
||||||
|
this.initEventDelegation();
|
||||||
|
}
|
||||||
|
|
||||||
|
initEventDelegation() {
|
||||||
|
// 鼠标进入容器暂停
|
||||||
|
this.container.addEventListener('mouseover', (e) => {
|
||||||
|
const item = e.target.closest('.barrage-item');
|
||||||
|
if (item) {
|
||||||
|
item.style.animationPlayState = 'paused';
|
||||||
|
item.style.zIndex = '9999';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 鼠标离开恢复
|
||||||
|
this.container.addEventListener('mouseout', (e) => {
|
||||||
|
const item = e.target.closest('.barrage-item');
|
||||||
|
if (item) {
|
||||||
|
item.style.animationPlayState = 'running';
|
||||||
|
item.style.zIndex = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 点击事件
|
||||||
|
this.container.addEventListener('click', (e) => {
|
||||||
|
const item = e.target.closest('.barrage-item');
|
||||||
|
if (item) {
|
||||||
|
const url = item.dataset.url;
|
||||||
|
if (url && url !== '#') {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const targetId = url.split('#')[1];
|
||||||
|
const targetEl = document.getElementById(targetId);
|
||||||
|
|
||||||
|
if (targetEl) {
|
||||||
|
targetEl.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||||
|
targetEl.classList.add('atk-flash');
|
||||||
|
setTimeout(() => targetEl.classList.remove('atk-flash'), 2000);
|
||||||
|
} else {
|
||||||
|
window.location.href = url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
start(data = []) {
|
start(data = []) {
|
||||||
@@ -180,6 +228,7 @@
|
|||||||
this.isDestroyed = true;
|
this.isDestroyed = true;
|
||||||
this.stop();
|
this.stop();
|
||||||
this.clearDOM();
|
this.clearDOM();
|
||||||
|
// 移除事件监听需要保存引用,这里因为容器可能被销毁,且是单例,暂不处理复杂的解绑
|
||||||
}
|
}
|
||||||
|
|
||||||
loop() {
|
loop() {
|
||||||
@@ -187,15 +236,15 @@
|
|||||||
|
|
||||||
// 容器检测
|
// 容器检测
|
||||||
if (!document.body.contains(this.container)) {
|
if (!document.body.contains(this.container)) {
|
||||||
// 尝试重新获取容器 (可能被 PJAX 替换但 ID 没变?)
|
|
||||||
// 这里简单处理:如果失效则停止
|
|
||||||
// console.warn('[Barrage] 容器失效,停止');
|
|
||||||
this.destroy();
|
this.destroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.isPaused && this.data.length > 0) {
|
if (!this.isPaused && this.data.length > 0) {
|
||||||
this.tryShoot();
|
// 只有当前屏幕数量未满时才发射
|
||||||
|
if (this.activeIds.size < this.maxActiveItems) {
|
||||||
|
this.tryShoot();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 随机间隔 2s - 4s
|
// 随机间隔 2s - 4s
|
||||||
@@ -226,33 +275,20 @@
|
|||||||
|
|
||||||
const item = document.createElement('div');
|
const item = document.createElement('div');
|
||||||
item.className = 'barrage-item';
|
item.className = 'barrage-item';
|
||||||
|
// 存储 URL 到 dataset 以供事件委托使用
|
||||||
|
if (url && url !== '#') {
|
||||||
|
item.dataset.url = url;
|
||||||
|
item.style.cursor = 'pointer';
|
||||||
|
}
|
||||||
|
|
||||||
let html = '';
|
let html = '';
|
||||||
|
// 优化:只有当有头像时才渲染 img 标签
|
||||||
if (avatar) {
|
if (avatar) {
|
||||||
html += `<img src="${avatar}" class="barrage-avatar" draggable="false">`;
|
html += `<img src="${avatar}" class="barrage-avatar" draggable="false" loading="lazy">`;
|
||||||
}
|
}
|
||||||
html += `<div class="barrage-bubble"><span class="barrage-text">${text}</span></div>`;
|
html += `<div class="barrage-bubble"><span class="barrage-text">${text}</span></div>`;
|
||||||
item.innerHTML = html;
|
item.innerHTML = html;
|
||||||
|
|
||||||
if (url && url !== '#') {
|
|
||||||
item.style.cursor = 'pointer';
|
|
||||||
item.addEventListener('click', (e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const targetId = url.split('#')[1];
|
|
||||||
const targetEl = document.getElementById(targetId);
|
|
||||||
|
|
||||||
if (targetEl) {
|
|
||||||
targetEl.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
||||||
targetEl.classList.add('atk-flash');
|
|
||||||
setTimeout(() => targetEl.classList.remove('atk-flash'), 2000);
|
|
||||||
} else {
|
|
||||||
window.location.href = url;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 样式与动画
|
// 样式与动画
|
||||||
const tracks = 10;
|
const tracks = 10;
|
||||||
const trackIndex = Math.floor(Math.random() * tracks);
|
const trackIndex = Math.floor(Math.random() * tracks);
|
||||||
@@ -263,15 +299,7 @@
|
|||||||
const duration = 18 + Math.random() * 7;
|
const duration = 18 + Math.random() * 7;
|
||||||
item.style.animation = `barrage-slide-right ${duration}s linear forwards`;
|
item.style.animation = `barrage-slide-right ${duration}s linear forwards`;
|
||||||
|
|
||||||
item.addEventListener('mouseenter', () => {
|
// 仅绑定必要的生命周期事件
|
||||||
item.style.animationPlayState = 'paused';
|
|
||||||
item.style.zIndex = '9999';
|
|
||||||
});
|
|
||||||
item.addEventListener('mouseleave', () => {
|
|
||||||
item.style.animationPlayState = 'running';
|
|
||||||
item.style.zIndex = '';
|
|
||||||
});
|
|
||||||
|
|
||||||
item.addEventListener('animationend', () => {
|
item.addEventListener('animationend', () => {
|
||||||
item.remove();
|
item.remove();
|
||||||
this.activeIds.delete(id);
|
this.activeIds.delete(id);
|
||||||
|
|||||||
Reference in new issue
Block a user