// ==UserScript== // @name 漫画图片网站自动触发懒加载 // @namespace http://tampermonkey/auto-scroll // @version 1.1 // @author Optimized // @description 智能滚动触发懒加载,控制面板自动隐藏为边缘竖线,支持自动开始、速度调节、暂停/继续 // @match http://*/* // @match https://*/* // @grant none // @license MIT // ==/UserScript== (function () { 'use strict'; // 配置项 const CONFIG = { time: 300, // 滚动间隔(ms) distance: 600, // 每次滚动距离(px) bottomThreshold: 100, // 距底部阈值(px) scrollBehavior: 'smooth', // 滚动行为 autoHideDelay: 2000, // 自动隐藏延迟(ms) hideOffset: -145, // 隐藏时偏移量(px) autoStart: true // 是否自动开始滚动 }; let scrollInterval = null; let isScrolling = false; let scrollCount = 0; let hideTimer = null; let isPanelVisible = true; // 创建UI控制器 function createController() { const container = document.createElement('div'); container.id = 'manga-scroll-controller'; container.innerHTML = `
🚀 自动开始
🫥 自动隐藏
准备就绪
`; document.body.appendChild(container); // 设置自动隐藏功能 setupAutoHide(container); // 设置自动开始功能 setupAutoStart(); } // 设置自动隐藏 function setupAutoHide(container) { const autoHideToggle = document.getElementById('auto-hide-toggle'); // 显示面板 function showPanel() { if (container.classList.contains('hidden')) { container.classList.remove('hidden'); isPanelVisible = true; } resetHideTimer(); } // 隐藏面板 function hidePanel() { if (!container.matches(':hover') && autoHideToggle.checked) { container.classList.add('hidden'); isPanelVisible = false; } } // 重置隐藏计时器 function resetHideTimer() { if (hideTimer) { clearTimeout(hideTimer); hideTimer = null; } // 如果开启了自动隐藏 if (autoHideToggle && autoHideToggle.checked) { hideTimer = setTimeout(() => { hidePanel(); }, CONFIG.autoHideDelay); } } // 鼠标进入面板 container.addEventListener('mouseenter', () => { if (hideTimer) { clearTimeout(hideTimer); hideTimer = null; } if (!isPanelVisible) { showPanel(); } }); // 鼠标离开面板 container.addEventListener('mouseleave', () => { if (autoHideToggle && autoHideToggle.checked) { hideTimer = setTimeout(() => { hidePanel(); }, 500); } }); // 面板内交互时重置计时器 container.addEventListener('click', resetHideTimer); container.addEventListener('input', resetHideTimer); container.addEventListener('focusin', resetHideTimer); // 自动隐藏开关变化 autoHideToggle.addEventListener('change', () => { if (autoHideToggle.checked) { resetHideTimer(); } else { if (hideTimer) { clearTimeout(hideTimer); hideTimer = null; } container.classList.remove('hidden'); isPanelVisible = true; } }); // 全局鼠标移动检测 document.addEventListener('mousemove', (e) => { if (!isPanelVisible && autoHideToggle && autoHideToggle.checked) { if (e.clientX <= 30) { const viewportHeight = window.innerHeight; const triggerZoneTop = viewportHeight * 0.2; const triggerZoneBottom = viewportHeight * 0.8; if (e.clientY >= triggerZoneTop && e.clientY <= triggerZoneBottom) { showPanel(); } } } }); // 初始自动隐藏 if (autoHideToggle.checked) { hideTimer = setTimeout(() => { hidePanel(); }, CONFIG.autoHideDelay); } } // 设置自动开始 function setupAutoStart() { const autoStartToggle = document.getElementById('auto-start-toggle'); // 保存自动开始设置到本地存储 function saveAutoStartSetting(enabled) { try { localStorage.setItem('manga-scroll-auto-start', enabled ? 'true' : 'false'); } catch (e) { // 忽略存储错误 } } // 加载自动开始设置 function loadAutoStartSetting() { try { const saved = localStorage.getItem('manga-scroll-auto-start'); if (saved !== null) { return saved === 'true'; } } catch (e) { // 忽略存储错误 } return CONFIG.autoStart; // 默认值 } // 初始化自动开始状态 const savedAutoStart = loadAutoStartSetting(); autoStartToggle.checked = savedAutoStart; CONFIG.autoStart = savedAutoStart; // 自动开始开关变化事件 autoStartToggle.addEventListener('change', () => { CONFIG.autoStart = autoStartToggle.checked; saveAutoStartSetting(CONFIG.autoStart); // 更新信息提示 if (CONFIG.autoStart) { updateInfo('已启用自动开始'); // 如果当前没有在滚动,自动开始 if (!isScrolling) { startScroll(); } } else { updateInfo('已禁用自动开始'); } }); // 页面加载时的行为 if (CONFIG.autoStart) { updateInfo('自动开始已启用'); } else { updateInfo('自动开始已禁用,点击按钮开始'); } } // 智能滚动 - 触发懒加载 function smartScroll() { const currentPosition = window.pageYOffset + window.innerHeight; const documentHeight = Math.max( document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight ); if (currentPosition + CONFIG.bottomThreshold >= documentHeight) { setTimeout(() => { const newHeight = Math.max( document.body.scrollHeight, document.documentElement.scrollHeight ); if (newHeight <= documentHeight + CONFIG.distance) { stopScroll(); updateInfo('已到底部,返回顶部'); setTimeout(() => { window.scrollTo({ top: 0, behavior: 'smooth' }); }, 1000); } else { updateInfo(`触发懒加载,继续滚动... (${++scrollCount})`); window.scrollBy({ top: CONFIG.distance, behavior: CONFIG.scrollBehavior }); } }, 500); } else { window.scrollBy({ top: CONFIG.distance, behavior: CONFIG.scrollBehavior }); scrollCount++; updateInfo(`滚动中... (${scrollCount}次)`); } } // 更新信息显示 function updateInfo(message) { const infoElement = document.getElementById('scroll-info'); if (infoElement) { infoElement.textContent = message; } } // 开始滚动 function startScroll() { if (!scrollInterval) { const time = parseInt(document.getElementById('scroll-time-input').value) || CONFIG.time; const distance = parseInt(document.getElementById('scroll-distance-input').value) || CONFIG.distance; CONFIG.time = time; CONFIG.distance = distance; smartScroll(); scrollInterval = setInterval(smartScroll, time); isScrolling = true; scrollCount = 0; const btn = document.getElementById('scroll-toggle-btn'); if (btn) { btn.textContent = '⏸ 暂停'; btn.classList.remove('paused'); } updateInfo('开始滚动...'); } } // 停止滚动 function stopScroll() { if (scrollInterval) { clearInterval(scrollInterval); scrollInterval = null; isScrolling = false; const btn = document.getElementById('scroll-toggle-btn'); if (btn) { btn.textContent = '▶ 继续'; btn.classList.add('paused'); } updateInfo('已暂停'); } } // 切换滚动状态 function toggleScroll() { if (isScrolling) { stopScroll(); } else { startScroll(); } } // 键盘快捷键 function setupKeyboardShortcuts() { document.addEventListener('keydown', (e) => { if (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') { return; } switch(e.key) { case ' ': e.preventDefault(); toggleScroll(); break; case 'ArrowUp': if (e.ctrlKey) { e.preventDefault(); document.getElementById('scroll-top-btn')?.click(); } break; case 'ArrowDown': if (e.ctrlKey) { e.preventDefault(); document.getElementById('scroll-bottom-btn')?.click(); } break; case 'h': if (e.ctrlKey && e.shiftKey) { e.preventDefault(); const autoHideToggle = document.getElementById('auto-hide-toggle'); if (autoHideToggle) { autoHideToggle.checked = !autoHideToggle.checked; autoHideToggle.dispatchEvent(new Event('change')); } } break; case 'a': if (e.ctrlKey && e.shiftKey) { e.preventDefault(); const autoStartToggle = document.getElementById('auto-start-toggle'); if (autoStartToggle) { autoStartToggle.checked = !autoStartToggle.checked; autoStartToggle.dispatchEvent(new Event('change')); } } break; } }); } // 初始化 function init() { createController(); setupKeyboardShortcuts(); document.getElementById('scroll-toggle-btn').addEventListener('click', toggleScroll); document.getElementById('scroll-top-btn').addEventListener('click', () => { window.scrollTo({ top: 0, behavior: 'smooth' }); }); document.getElementById('scroll-bottom-btn').addEventListener('click', () => { window.scrollTo({ top: document.documentElement.scrollHeight, behavior: 'smooth' }); }); ['scroll-time-input', 'scroll-distance-input'].forEach(id => { document.getElementById(id).addEventListener('change', () => { if (isScrolling) { stopScroll(); startScroll(); } }); }); window.addEventListener('beforeunload', () => { stopScroll(); if (hideTimer) { clearTimeout(hideTimer); } }); // 根据自动开始设置决定是否自动开始滚动 if (CONFIG.autoStart) { startScroll(); } else { // 不自动开始,但准备好界面 const btn = document.getElementById('scroll-toggle-btn'); if (btn) { btn.textContent = '▶ 开始'; btn.classList.add('paused'); } } console.log('漫画懒加载滚动器已启动 | 快捷键: 空格暂停 | Ctrl+Shift+A 切换自动开始 | Ctrl+Shift+H 切换自动隐藏 | Ctrl+↑↓ 跳转'); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();