您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
鼠标悬停显示放大按钮,点击放大并支持滚轮缩放
+ // ==UserScript== // @name 图片悬停放大工具 // @namespace http://tampermonkey.net/ // @version 0.2 // @description 鼠标悬停显示放大按钮,点击放大并支持滚轮缩放 // @author clownvary // @match *://*/* // @grant GM_addStyle // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_getValue // @license MIT // ==/UserScript== // 添加必要的样式 GM_addStyle(` .zoom-btn { position: absolute; top: 5px; right: 5px; background: rgba(0,0,0,0.5); color: white; width: 20px; height: 20px; border-radius: 50%; display: none; align-items: center; justify-content: center; cursor: pointer; z-index: 9999; } .zoom-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); display: none; justify-content: center; align-items: center; z-index: 10000; } .zoomed-img { max-width: 90%; max-height: 90%; object-fit: contain; transform-origin: center center; user-select: none; -webkit-user-drag: none; } `); (function() { 'use strict'; // 网站特定规则配置 const siteRules = { 'example.com': { selector: '.original-image', // 原图元素选择器 attribute: 'src', // 原图URL属性 parentSelector: '.image-wrapper', // 父元素选择器 siblingSelector: '.hd-image', // 兄弟元素选择器 } }; // 获取当前网站的规则 function getSiteRule() { const hostname = window.location.hostname; return siteRules[hostname]; } // 智能查找原图URL function getOriginalImageUrl(img) { // 处理Twitter图片 if (img.src && img.src.includes('twimg.com')) { return img.src.replace(/\?format=.+$/, '?format=jpg&name=orig'); } // 1. 检查用户是否手动设置了该图片的原图URL const manualUrls = GM_getValue('manualImageUrls', {}); if (manualUrls[img.src]) { return manualUrls[img.src]; } // 2. 检查网站特定规则 const siteRule = getSiteRule(); if (siteRule) { // 根据规则查找原图 if (siteRule.parentSelector) { const parent = img.closest(siteRule.parentSelector); if (parent) { const originalImg = parent.querySelector(siteRule.selector); if (originalImg && originalImg[siteRule.attribute]) { return originalImg[siteRule.attribute]; } } } } // 3. 常见属性检查 const commonAttributes = [ 'data-original', 'data-src', 'data-full', 'data-zoom-src', 'data-big', 'data-actualsrc', 'data-original-src' ]; for (const attr of commonAttributes) { const value = img.getAttribute(attr); if (value) return value; } // 4. 检查父级a标签 const parentLink = img.closest('a'); if (parentLink && /\.(jpe?g|png|gif|webp)($|\?)/i.test(parentLink.href)) { return parentLink.href; } // 5. 检查兄弟节点 const siblings = img.parentElement.children; for (const sibling of siblings) { if (sibling !== img && sibling.tagName === 'IMG') { const siblingUrl = sibling.src || sibling.getAttribute('data-src'); if (siblingUrl && siblingUrl.includes('original')) { return siblingUrl; } } } // 6. 尝试修改URL参数来获取大图 const urlPatterns = [ { pattern: /(_thumb|_small|_mini)/i, replacement: '' }, { pattern: /\b(width|height|size)=\d+/i, replacement: '' }, { pattern: /\bw=\d+/i, replacement: '' }, { pattern: /\bq=\d+/i, replacement: 'q=100' } ]; let originalUrl = img.src; for (const {pattern, replacement} of urlPatterns) { if (pattern.test(originalUrl)) { return originalUrl.replace(pattern, replacement); } } // 最后返回原始src return img.src; } // 添加右键菜单处理 function addContextMenu(img, zoomBtn) { zoomBtn.addEventListener('contextmenu', (e) => { e.preventDefault(); const manualUrl = prompt('请输入此图片的原图URL:'); if (manualUrl) { const manualUrls = GM_getValue('manualImageUrls', {}); manualUrls[img.src] = manualUrl; GM_setValue('manualImageUrls', manualUrls); alert('设置成功!'); } }); } // 为所有图片添加放大功能 function initializeImages() { // 处理普通的img标签 document.querySelectorAll('img').forEach(handleImage); // 针对Twitter的特定选择器 if (window.location.hostname.includes('twitter.com')) { document.querySelectorAll('div[style*="background-image"]').forEach(handleBackgroundImage); } // 其他网站的背景图片处理(可以根据需要添加特定选择器) const bgImageSelectors = [ 'div[style*="background-image"]', '.image-bg', // 示例:特定类名 '[data-bg-image]' // 示例:特定属性 ]; if (!window.location.hostname.includes('twitter.com')) { document.querySelectorAll(bgImageSelectors.join(',')).forEach(handleBackgroundImage); } } // 处理背景图片元素 function handleBackgroundImage(element) { if (element.dataset.zoomInitialized) return; element.dataset.zoomInitialized = 'true'; // 获取背景图片URL const bgImage = window.getComputedStyle(element).backgroundImage; const url = bgImage.replace(/^url\(['"]?(.+?)['"]?\)$/, '$1'); if (!url || url === 'none') return; // 创建放大按钮 const zoomBtn = document.createElement('div'); zoomBtn.className = 'zoom-btn'; zoomBtn.innerHTML = '+'; // 确保父元素是relative定位 const position = window.getComputedStyle(element).position; if (position === 'static') { element.style.position = 'relative'; } element.appendChild(zoomBtn); // 鼠标悬停显示放大按钮 element.addEventListener('mouseenter', () => { zoomBtn.style.display = 'flex'; }); element.addEventListener('mouseleave', () => { zoomBtn.style.display = 'none'; }); // 点击放大按钮 zoomBtn.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); const originalUrl = url.includes('twimg.com') ? url.replace(/\?format=.+$/, '?format=jpg&name=orig') : url; showZoomedImage(originalUrl); return false; }, true); } // 处理普通图片元素 function handleImage(img) { if (img.dataset.zoomInitialized) return; img.dataset.zoomInitialized = 'true'; const wrapper = document.createElement('div'); wrapper.style.position = 'relative'; wrapper.style.display = 'inline-block'; img.parentNode.insertBefore(wrapper, img); wrapper.appendChild(img); const zoomBtn = document.createElement('div'); zoomBtn.className = 'zoom-btn'; zoomBtn.innerHTML = '+'; wrapper.appendChild(zoomBtn); // 添加右键菜单功能 addContextMenu(img, zoomBtn); wrapper.addEventListener('mouseenter', () => { zoomBtn.style.display = 'flex'; }); wrapper.addEventListener('mouseleave', () => { zoomBtn.style.display = 'none'; }); zoomBtn.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); const originalUrl = getOriginalImageUrl(img); showZoomedImage(originalUrl); return false; }, true); } // 更新MutationObserver以使用节流 const throttle = (func, limit) => { let inThrottle; return function() { const args = arguments; const context = this; if (!inThrottle) { func.apply(context, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } } } const observer = new MutationObserver( throttle((mutations) => { initializeImages(); }, 1000) // 1秒节流 ); observer.observe(document.body, { childList: true, subtree: true }); // 初始化 initializeImages(); // 添加菜单命令 GM_registerMenuCommand('清除手动设置的原图URL', () => { GM_setValue('manualImageUrls', {}); alert('已清除所有手动设置的原图URL!'); }); // 创建放大图片的遮罩层 const overlay = document.createElement('div'); overlay.className = 'zoom-overlay'; document.body.appendChild(overlay); function showZoomedImage(src) { const img = document.createElement('img'); img.className = 'zoomed-img'; // 添加加载指示器 const loadingDiv = document.createElement('div'); loadingDiv.textContent = '加载中...'; loadingDiv.style.color = 'white'; overlay.innerHTML = ''; overlay.appendChild(loadingDiv); overlay.style.display = 'flex'; // 图片加载完成后显示 img.addEventListener('load', () => { overlay.innerHTML = ''; overlay.appendChild(img); overlay.style.display = 'flex'; let scale = 1; let isDragging = false; let startX, startY; let translateX = 0; let translateY = 0; // 添加滚轮缩放 img.addEventListener('wheel', (e) => { e.preventDefault(); const delta = e.deltaY > 0 ? -0.1 : 0.1; scale = Math.max(0.1, scale + delta); updateTransform(); }); // 鼠标按下开始拖动 img.addEventListener('mousedown', (e) => { isDragging = true; startX = e.clientX - translateX; startY = e.clientY - translateY; img.style.cursor = 'grabbing'; }); // 鼠标移动时更新位置 document.addEventListener('mousemove', (e) => { if (!isDragging) return; translateX = e.clientX - startX; translateY = e.clientY - startY; updateTransform(); }); // 鼠标松开停止拖动 document.addEventListener('mouseup', () => { isDragging = false; img.style.cursor = 'grab'; }); // 更新变换 function updateTransform() { img.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scale})`; } // 初始化鼠标样式 img.style.cursor = 'grab'; // 点击遮罩层关闭(但不包括图片) overlay.addEventListener('click', (e) => { if (e.target === overlay) { overlay.style.display = 'none'; // 清除拖动相关的事件监听器 document.removeEventListener('mousemove', null); document.removeEventListener('mouseup', null); } }); }); // 设置图片的src img.src = src; } })();