// ==UserScript== // @name Bilibili 评论区右置无感预载版 // @namespace http://tampermonkey.net/ // @version 2.0 // @description 将B站视频评论区常驻右侧(默认完全透明且不挡交互),实现后台静默预载。点击悬浮球极速淡入,消除加载闪烁与拖沓的滑出动画。 // @author bili_user_helper // @match *://www.bilibili.com/video/* // @match *://www.bilibili.com/bangumi/play/* // @match *://www.bilibili.com/list/* // @icon https://www.bilibili.com/favicon.ico // @grant none // @run-at document-start // ==/UserScript== (function() { 'use strict'; // 预定义样式,确保在DOM解析第一阶段生效,防止任何首屏底部闪烁 const css = ` /* 核心预载逻辑:常驻屏幕可视区,让B站以为其已曝光从而在后台静默加载评论,同时默认透明且不遮挡任何底层交互 */ #comment, #comment-module, .comment-container, .bili-comment-container, #commentapp, .bili-comment-sidebar { position: fixed !important; top: 0 !important; right: 0 !important; width: 460px !important; height: 100vh !important; z-index: 99999 !important; background-color: var(--bg1, #ffffff) !important; box-shadow: -5px 0 25px rgba(0,0,0,0.12) !important; box-sizing: border-box !important; padding: 15px 20px 20px 20px !important; overflow-y: auto !important; border-left: 1px solid var(--line_regular, #e3e8ec) !important; /* 默认完全透明,不阻挡鼠标点击底层推荐栏 */ opacity: 0 !important; pointer-events: none !important; /* 极速淡入淡出,消除拖沓的位移动画感 */ transition: opacity 0.15s ease-in-out !important; } /* 展开状态 */ #comment.expanded, #comment-module.expanded, .comment-container.expanded, .bili-comment-container.expanded, #commentapp.expanded, .bili-comment-sidebar.expanded { opacity: 1 !important; pointer-events: auto !important; } /* 侧边栏内部元素自适应调节 */ .bili-comment-sidebar .reply-navigation, .bili-comment-sidebar .reply-send, .bili-comment-sidebar .comment-container, .bili-comment-sidebar .comment-send, .bili-comment-sidebar .reply-list, .bili-comment-sidebar .reply-item, .bili-comment-sidebar bili-comments { width: 100% !important; max-width: 100% !important; box-sizing: border-box !important; } /* 隐藏B站自带的顶部多余外边距 */ .bili-comment-sidebar .reply-header { border-top: none !important; margin-top: 0 !important; } /* 自定义粘性控制头部 */ .bili-comment-sidebar-header { display: flex !important; align-items: center !important; justify-content: space-between !important; padding-bottom: 12px !important; margin-bottom: 12px !important; border-bottom: 1px solid var(--line_regular, #e3e8ec) !important; background-color: var(--bg1, #ffffff) !important; position: sticky !important; top: 0 !important; z-index: 100000 !important; } .bili-comment-sidebar-title { font-size: 16px !important; font-weight: bold !important; color: var(--text1, #18191c) !important; display: flex !important; align-items: center !important; gap: 8px !important; } .bili-comment-sidebar-close { background: none !important; border: none !important; cursor: pointer !important; color: var(--text2, #9499a0) !important; display: flex !important; align-items: center !important; justify-content: center !important; padding: 4px !important; border-radius: 4px !important; transition: background-color 0.2s, color 0.2s !important; } .bili-comment-sidebar-close:hover { background-color: var(--bg2, #f1f2f3) !important; color: var(--text1, #18191c) !important; } /* 滚动条美化 */ .bili-comment-sidebar::-webkit-scrollbar { width: 6px !important; } .bili-comment-sidebar::-webkit-scrollbar-thumb { background-color: var(--text3, #c9ccd0) !important; border-radius: 3px !important; } .bili-comment-sidebar::-webkit-scrollbar-track { background: transparent !important; } /* 悬浮球样式 */ #bili-comment-ball { position: fixed !important; right: 24px !important; bottom: 140px !important; width: 48px !important; height: 48px !important; border-radius: 50% !important; background-color: #fb7299 !important; color: #ffffff !important; box-shadow: 0 4px 12px rgba(251, 114, 153, 0.4) !important; display: flex !important; align-items: center !important; justify-content: center !important; cursor: pointer !important; z-index: 100001 !important; transition: right 0.2s cubic-bezier(0.25, 0.8, 0.25, 1), transform 0.2s ease, background-color 0.2s ease !important; user-select: none !important; } #bili-comment-ball:hover { transform: scale(1.08) !important; background-color: #fc8bab !important; } /* 侧边栏激活时悬浮球随之左移 */ .bili-comment-sidebar-active #bili-comment-ball { right: 484px !important; /* 460px sidebar + 24px spacing */ background-color: #fb7299 !important; box-shadow: -4px 4px 12px rgba(0,0,0,0.15) !important; } @media (max-width: 768px) { .bili-comment-sidebar { width: 100% !important; } .bili-comment-sidebar-active #bili-comment-ball { right: calc(100% - 60px) !important; } } `; // 尽早注入 CSS 规则 const injectStyle = () => { const style = document.createElement('style'); style.textContent = css; if (document.documentElement) { document.documentElement.appendChild(style); } else { const observer = new MutationObserver(() => { if (document.documentElement) { document.documentElement.appendChild(style); observer.disconnect(); } }); observer.observe(document, { childList: true, subtree: true }); } }; injectStyle(); const selectors = [ '#comment', '#comment-module', '.comment-container', '.bili-comment-container', '#commentapp' ]; let isExpanded = false; function getCommentElement() { for (const selector of selectors) { const el = document.querySelector(selector); if (el) return el; } return null; } // 初始化评论区容器 function initCommentSidebar(el) { if (el.classList.contains('bili-comment-sidebar')) return; el.classList.add('bili-comment-sidebar'); // 注入头部控制栏 if (!el.querySelector('.bili-comment-sidebar-header')) { const header = document.createElement('div'); header.className = 'bili-comment-sidebar-header'; header.innerHTML = ` 视频评论区 `; header.querySelector('.bili-comment-sidebar-close').addEventListener('click', (e) => { e.stopPropagation(); collapseSidebar(); }); el.insertBefore(header, el.firstChild); } // 滚动事件转发 el.addEventListener('scroll', () => { window.dispatchEvent(new Event('scroll')); }); } function toggleSidebar() { isExpanded = !isExpanded; updateSidebarState(); if (isExpanded) { // 补偿触发一次全局滚动,确保最新数据获取 setTimeout(() => { window.dispatchEvent(new Event('scroll')); }, 50); } } function collapseSidebar() { isExpanded = false; updateSidebarState(); } function updateSidebarState() { const commentEl = getCommentElement(); if (isExpanded) { document.body.classList.add('bili-comment-sidebar-active'); if (commentEl) { commentEl.classList.add('expanded'); } } else { document.body.classList.remove('bili-comment-sidebar-active'); if (commentEl) { commentEl.classList.remove('expanded'); } } } // 拖拽与交互设置 function setupBallInteractions(ball) { let isDragging = false; let startY = 0; let initialTop = 0; const handleMove = (clientY) => { let newTop = initialTop + (clientY - startY); const margin = 10; const ballHeight = ball.offsetHeight || 48; if (newTop < margin) newTop = margin; if (newTop > window.innerHeight - ballHeight - margin) { newTop = window.innerHeight - ballHeight - margin; } ball.style.top = newTop + 'px'; ball.style.bottom = 'auto'; }; ball.addEventListener('mousedown', (e) => { if (e.button !== 0) return; isDragging = false; startY = e.clientY; initialTop = ball.getBoundingClientRect().top; const onMouseMove = (moveEvent) => { const deltaY = moveEvent.clientY - startY; if (Math.abs(deltaY) > 5) { isDragging = true; } if (isDragging) { handleMove(moveEvent.clientY); } }; const onMouseUp = () => { document.removeEventListener('mousemove', onMouseMove); document.removeEventListener('mouseup', onMouseUp); }; document.addEventListener('mousemove', onMouseMove); document.addEventListener('mouseup', onMouseUp); }); ball.addEventListener('touchstart', (e) => { isDragging = false; startY = e.touches[0].clientY; initialTop = ball.getBoundingClientRect().top; const onTouchMove = (moveEvent) => { const deltaY = moveEvent.touches[0].clientY - startY; if (Math.abs(deltaY) > 5) { isDragging = true; } if (isDragging) { handleMove(moveEvent.touches[0].clientY); } }; const onTouchEnd = () => { document.removeEventListener('touchmove', onTouchMove); document.removeEventListener('touchend', onTouchEnd); }; document.addEventListener('touchmove', onTouchMove); document.addEventListener('touchend', onTouchEnd); }); ball.addEventListener('click', (e) => { if (isDragging) { e.preventDefault(); e.stopPropagation(); return; } toggleSidebar(); }); } function createFloatingBall() { if (document.getElementById('bili-comment-ball')) return; const ball = document.createElement('div'); ball.id = 'bili-comment-ball'; ball.title = '展开/折叠评论区'; ball.innerHTML = ` `; document.body.appendChild(ball); setupBallInteractions(ball); } // 页面加载完成后,触发一次模拟滚动以激活静默预载 window.addEventListener('DOMContentLoaded', () => { createFloatingBall(); setTimeout(() => { window.dispatchEvent(new Event('scroll')); }, 300); }); // 循环监听支持 B站 SPA setInterval(() => { createFloatingBall(); const commentEl = getCommentElement(); if (commentEl) { initCommentSidebar(commentEl); if (isExpanded) { commentEl.classList.add('expanded'); document.body.classList.add('bili-comment-sidebar-active'); } else { commentEl.classList.remove('expanded'); document.body.classList.remove('bili-comment-sidebar-active'); } } }, 500); })();