// ==UserScript== // @name 万能懒加载触发 + 超级视窗缩放(面板可拖拽) // @namespace qq:1316590732 // @version 9.1 // @description 修复三种懒加载模式 + 可拖拽面板 + 优化按钮样式 // @author 沧桑 // @match *://*/* // @grant none // @license MIT // @run-at document-start // @downloadURL https://update.greasyfork.icu/scripts/576141/%E4%B8%87%E8%83%BD%E6%87%92%E5%8A%A0%E8%BD%BD%E8%A7%A6%E5%8F%91%20%2B%20%E8%B6%85%E7%BA%A7%E8%A7%86%E7%AA%97%E7%BC%A9%E6%94%BE%EF%BC%88%E9%9D%A2%E6%9D%BF%E5%8F%AF%E6%8B%96%E6%8B%BD%EF%BC%89.user.js // @updateURL https://update.greasyfork.icu/scripts/576141/%E4%B8%87%E8%83%BD%E6%87%92%E5%8A%A0%E8%BD%BD%E8%A7%A6%E5%8F%91%20%2B%20%E8%B6%85%E7%BA%A7%E8%A7%86%E7%AA%97%E7%BC%A9%E6%94%BE%EF%BC%88%E9%9D%A2%E6%9D%BF%E5%8F%AF%E6%8B%96%E6%8B%BD%EF%BC%89.meta.js // ==/UserScript== (function () { 'use strict'; let currentZoom = 1; let panel = null; let isDragging = false; let startX = 0, startY = 0, startLeft = 0, startTop = 0; let scrollInterval = null; // 用于控制滚动频率 // ========== 核心缩放函数 ========== function setZoom(zoomLevel) { currentZoom = Math.max(0.0001, Math.min(50, zoomLevel)); if ('zoom' in document.body.style) { document.body.style.zoom = currentZoom; } else { document.body.style.transform = `scale(${currentZoom})`; document.body.style.transformOrigin = '0 0'; } updateZoomDisplay(); } function updateZoomDisplay() { if (!panel) return; const display = panel.querySelector('#currentZoomDisplay'); if (display) { display.textContent = currentZoom < 0.01 ? `${currentZoom.toExponential(4)} 倍` : `${currentZoom.toFixed(4)} 倍`; } } // ========== 模拟真实鼠标事件 ========== function simulateMouseEvent(element, eventType) { if (!element) return; const rect = element.getBoundingClientRect(); const x = rect.left + rect.width / 2; const y = rect.top + rect.height / 2; const event = new MouseEvent(eventType, { view: window, bubbles: true, cancelable: true, clientX: x, clientY: y, screenX: x, screenY: y }); element.dispatchEvent(event); } // ========== 触发当前视口内所有图片的加载 ========== function triggerImagesInViewport() { const viewportHeight = window.innerHeight; const viewportWidth = window.innerWidth; const scrollX = window.scrollX || window.pageXOffset; const scrollY = window.scrollY || window.pageYOffset; // 获取所有可能的懒加载图片 const selectors = [ 'img[data-src]', 'img[data-original]', 'img[data-lazy]', 'img[data-lazy-src]', 'img[data-srcset]', 'img[loading="lazy"]', 'img[data-echo]', 'img[data-url]', 'img[data-srcset]', 'img[data-ks-lazyload]', 'img[srcset]', 'img:not([src])', 'iframe[data-src]', 'iframe[data-lazy]' ]; const allImages = document.querySelectorAll(selectors.join(',')); let loadedCount = 0; allImages.forEach(img => { const rect = img.getBoundingClientRect(); // 检查是否在视口内或接近视口(增加200px缓冲) const isInViewport = ( rect.top < viewportHeight + 200 && rect.bottom > -200 && rect.left < viewportWidth + 200 && rect.right > -200 ); if (isInViewport) { // 模拟鼠标悬停 simulateMouseEvent(img, 'mouseenter'); simulateMouseEvent(img, 'mouseover'); // 强制加载图片 if (img.tagName === 'IMG') { if (img.dataset.src && !img.src) img.src = img.dataset.src; if (img.dataset.original && !img.src) img.src = img.dataset.original; if (img.dataset.lazy && !img.src) img.src = img.dataset.lazy; if (img.dataset.lazySrc && !img.src) img.src = img.dataset.lazySrc; if (img.dataset.url && !img.src) img.src = img.dataset.url; if (img.dataset.echo && !img.src) img.src = img.dataset.echo; // 处理 srcset if (img.dataset.srcset && !img.srcset) img.srcset = img.dataset.srcset; loadedCount++; } else if (img.tagName === 'IFRAME') { if (img.dataset.src && !img.src) img.src = img.dataset.src; if (img.dataset.lazy && !img.src) img.src = img.dataset.lazy; loadedCount++; } } }); if (loadedCount > 0) { console.log(`[懒加载] 触发加载 ${loadedCount} 个资源`); } // 触发全局事件 window.dispatchEvent(new Event('scroll')); window.dispatchEvent(new Event('resize')); document.dispatchEvent(new Event('scroll')); document.dispatchEvent(new Event('visibilitychange')); } // ========== 滚动时持续触发加载 ========== function startContinuousTrigger() { if (scrollInterval) clearInterval(scrollInterval); // 每200ms触发一次视口内图片检查 scrollInterval = setInterval(() => { triggerImagesInViewport(); }, 200); } function stopContinuousTrigger() { if (scrollInterval) { clearInterval(scrollInterval); scrollInterval = null; } } // ========== 改进后的懒加载滚动 ========== async function triggerLazyLoad(mode = 'vertical') { console.log(`[懒加载] 开始触发 → 模式: ${mode}`); // 启动持续触发 startContinuousTrigger(); // 先重置到左上角 window.scrollTo({ left: 0, top: 0, behavior: 'auto' }); // 触发一次初始加载 triggerImagesInViewport(); await sleep(300); const totalHeight = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight); const totalWidth = Math.max(document.documentElement.scrollWidth, document.body.scrollWidth); const step = Math.max(220, window.innerHeight * 0.7); // 垂直步长 const hStep = Math.max(280, window.innerWidth * 0.75); // 水平步长 let pos = 0; if (mode === 'horizontal-ltr') { // 从左往右 pos = 0; while (pos <= totalWidth + 600) { window.scrollTo({ left: pos, top: 0, behavior: 'auto' }); await sleep(250); // 增加停留时间,让懒加载有机会加载 triggerImagesInViewport(); // 滚动后立即触发 await sleep(150); pos += hStep; } window.scrollTo({ left: 0, top: 0, behavior: 'smooth' }); } else if (mode === 'horizontal-rtl') { // 从右往左 pos = totalWidth; while (pos >= -600) { window.scrollTo({ left: pos, top: 0, behavior: 'auto' }); await sleep(250); triggerImagesInViewport(); await sleep(150); pos -= hStep; } window.scrollTo({ left: totalWidth, top: 0, behavior: 'smooth' }); } else { // 从上往下(默认) pos = 0; while (pos <= totalHeight + 600) { window.scrollTo({ top: pos, left: 0, behavior: 'auto' }); await sleep(250); triggerImagesInViewport(); await sleep(150); pos += step; } window.scrollTo({ top: 0, behavior: 'smooth' }); } // 最终再触发一次所有图片 await sleep(500); triggerAllImagesManually(); // 停止持续触发 stopContinuousTrigger(); console.log('[懒加载] 完成'); } function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // ========== 加强版手动触发所有图片和iframe加载 ========== function triggerAllImagesManually() { const selectors = [ 'img[data-src]', 'img[data-original]', 'img[data-lazy]', 'img[data-lazy-src]', 'img[data-srcset]', 'img[loading="lazy"]', 'img[data-echo]', 'img[data-url]', 'img:not([src])', 'img[src=""]', 'img[src="#"]', 'iframe[data-src]', 'iframe[data-lazy]' ]; let loadedCount = 0; document.querySelectorAll(selectors.join(',')).forEach(el => { if (el.tagName === 'IMG') { // 模拟鼠标事件 simulateMouseEvent(el, 'mouseenter'); simulateMouseEvent(el, 'mouseover'); if (el.dataset.src && !el.src) { el.src = el.dataset.src; loadedCount++; } if (el.dataset.original && !el.src) { el.src = el.dataset.original; loadedCount++; } if (el.dataset.lazy && !el.src) { el.src = el.dataset.lazy; loadedCount++; } if (el.dataset.lazySrc && !el.src) { el.src = el.dataset.lazySrc; loadedCount++; } if (el.dataset.url && !el.src) { el.src = el.dataset.url; loadedCount++; } if (el.dataset.srcset && !el.srcset) { el.srcset = el.dataset.srcset; loadedCount++; } } else if (el.tagName === 'IFRAME') { if (el.dataset.src && !el.src) { el.src = el.dataset.src; loadedCount++; } if (el.dataset.lazy && !el.src) { el.src = el.dataset.lazy; loadedCount++; } } }); if (loadedCount > 0) { console.log(`[手动触发] 强制加载 ${loadedCount} 个资源`); } // 触发全局事件 window.dispatchEvent(new Event('scroll')); document.dispatchEvent(new Event('scroll')); document.body.dispatchEvent(new Event('mouseenter')); } // ========== 使用MutationObserver监听新添加的图片 ========== function observeNewImages() { const observer = new MutationObserver((mutations) => { let hasNewImages = false; mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { if (node.nodeType === 1) { // Element node if (node.tagName === 'IMG' || node.tagName === 'IFRAME') { hasNewImages = true; } if (node.querySelectorAll) { const images = node.querySelectorAll('img, iframe'); if (images.length > 0) hasNewImages = true; } } }); }); if (hasNewImages) { setTimeout(() => triggerImagesInViewport(), 100); } }); observer.observe(document.body, { childList: true, subtree: true }); console.log('[监听] 已启用新图片监听'); } // ========== 创建面板(保持之前样式) ========== function createPanel() { if (panel && document.documentElement.contains(panel)) return; panel = document.createElement('div'); panel.id = 'super-zoom-panel'; Object.assign(panel.style, { position: 'fixed', top: '20px', right: '20px', width: '350px', background: 'linear-gradient(135deg, #667eea, #764ba2)', color: 'white', borderRadius: '16px', padding: '18px', boxShadow: '0 12px 50px rgba(0,0,0,0.45)', zIndex: '2147483647', fontFamily: 'system-ui, sans-serif', backdropFilter: 'blur(12px)', border: '1px solid rgba(255,255,255,0.3)', userSelect: 'none', transform: 'none !important', zoom: '1 !important' }); panel.innerHTML = `