您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
稳定版图片隐藏/显示工具,解决错位问题,确保所有图片显示控制按钮,图片消失时自动清理控制元素
// ==UserScript== // @name 更好用的脚本!控制页面的图片显示与隐藏 // @version 6.2 // @description 稳定版图片隐藏/显示工具,解决错位问题,确保所有图片显示控制按钮,图片消失时自动清理控制元素 // @author hulada // @match *://*/* // @grant none // @license MIT // @run-at document-body // @namespace https://greasyfork.org/users/1043548 // ==/UserScript== (function () { let active = false; let currentX, currentY, initialX, initialY, xOffset = 0, yOffset = 0, startTime = 0; window.imgHidenSet = null; window.imgShownSet = null; let yanEmoji = ["(‐^▽^‐)"]; let randomNumSet; // 存储所有图片元素及其对应的控制按钮和轮廓 let imageControls = new Map(); let imageOutlines = new Map(); let mouseTimers = new Map(); // 自动隐藏延迟时间(毫秒) const AUTO_HIDE_DELAY = 500; // 简单的节流函数 function throttle(func, delay) { let timeout; return function(...args) { if (!timeout) { timeout = setTimeout(() => { func.apply(this, args); timeout = null; }, delay); } }; } let toggleSingleImage = function(img, button, outline) { if (img.style.visibility === 'hidden' || img.style.visibility === '') { img.style.visibility = 'visible'; img.style.transition = 'filter 0.6s ease'; img.style.filter = 'none'; outline.style.display = 'none'; button.innerText = '隐'; button.title = '点击隐藏图片'; } else { img.style.visibility = 'hidden'; img.style.transition = 'filter 0.6s ease'; img.style.filter = 'blur(14px)'; outline.style.display = 'block'; button.innerText = '显'; button.title = '点击显示图片'; } }; let startAutoHideTimer = function(button, outline) { clearAutoHideTimer(button); mouseTimers.set(button, setTimeout(() => { button.style.opacity = '0.35'; outline.style.opacity = '0.35'; }, AUTO_HIDE_DELAY)); }; let clearAutoHideTimer = function(button) { if (mouseTimers.has(button)) { clearTimeout(mouseTimers.get(button)); mouseTimers.delete(button); } }; let createImageOutline = function(img) { if (imageOutlines.has(img)) return imageOutlines.get(img); let outline = document.createElement('div'); outline.style.position = 'absolute'; outline.style.zIndex = '999998'; outline.style.border = '2px dashed rgba(128, 128, 128, 0.6)'; outline.style.pointerEvents = 'none'; outline.style.transition = 'opacity 0.3s ease'; outline.style.display = 'none'; document.body.appendChild(outline); imageOutlines.set(img, outline); return outline; }; // 清理已消失的图片控制元素 let cleanupOrphanedControls = function() { const controlsToRemove = []; const outlinesToRemove = []; // 检查每个图片是否仍然存在且可见 imageControls.forEach((button, img) => { if (!img || !img.isConnected || img.offsetWidth === 0 || img.offsetHeight === 0) { controlsToRemove.push(img); } }); // 清理孤立的控制元素 controlsToRemove.forEach(img => { const button = imageControls.get(img); const outline = imageOutlines.get(img); if (button) { // 清理定时器 clearAutoHideTimer(button); // 移除DOM元素 if (button.parentNode) { button.parentNode.removeChild(button); } imageControls.delete(img); } if (outline) { if (outline.parentNode) { outline.parentNode.removeChild(outline); } imageOutlines.delete(img); } }); }; // 简化的位置更新(包含清理功能) let updatePositions = throttle(function() { // 先清理孤立的控制元素 cleanupOrphanedControls(); imageControls.forEach((button, img) => { if (!img || !img.isConnected) return; const rect = img.getBoundingClientRect(); const scrollX = window.pageXOffset || document.documentElement.scrollLeft; const scrollY = window.pageYOffset || document.documentElement.scrollTop; // 检查图片是否仍然可见 if (rect.width === 0 || rect.height === 0 || img.offsetWidth === 0 || img.offsetHeight === 0) { return; } // 更新按钮位置 button.style.left = (rect.left + scrollX + 8) + 'px'; button.style.top = (rect.top + scrollY + 8) + 'px'; // 更新轮廓位置 const outline = imageOutlines.get(img); if (outline) { outline.style.left = (rect.left + scrollX - 3) + 'px'; outline.style.top = (rect.top + scrollY - 3) + 'px'; outline.style.width = (rect.width + 4) + 'px'; outline.style.height = (rect.height + 4) + 'px'; } }); }, 200); let createImageControlButton = function(img) { if (imageControls.has(img)) return; let button = document.createElement('div'); button.innerText = '显'; button.title = '点击隐藏图片'; let outline = createImageOutline(img); // 样式设置 button.style.position = 'absolute'; button.style.zIndex = '999999'; button.style.padding = '4px 8px'; button.style.background = 'rgba(96, 96, 96, 0.8)'; button.style.border = '1px solid rgba(128, 128, 128, 0.9)'; button.style.color = 'rgba(240, 240, 240, 1)'; button.style.fontSize = '12px'; button.style.fontFamily = 'Arial, sans-serif'; button.style.lineHeight = '1.2'; button.style.textAlign = 'center'; button.style.cursor = 'pointer'; button.style.borderRadius = '4px'; button.style.transition = 'opacity 0.3s ease'; button.style.userSelect = 'none'; // 初始位置 updatePositions(); // 事件处理 button.addEventListener('mouseenter', function() { clearAutoHideTimer(button); button.style.opacity = '1'; button.style.background = 'rgba(128, 128, 128, 0.9)'; outline.style.opacity = '1'; }); button.addEventListener('mouseleave', function() { startAutoHideTimer(button, outline); button.style.background = 'rgba(96, 96, 96, 0.8)'; outline.style.opacity = '0.3'; }); button.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); toggleSingleImage(img, button, outline); clearAutoHideTimer(button); button.style.opacity = '1'; }); document.body.appendChild(button); imageControls.set(img, button); // 初始状态 if (img.style.visibility !== 'hidden') { img.style.visibility = 'hidden'; img.style.transition = 'filter 0.6s ease'; img.style.filter = 'blur(14px)'; outline.style.display = 'block'; } startAutoHideTimer(button, outline); }; // 查找所有图片 let findAllImages = function() { let images = []; // 标准图片 document.querySelectorAll('img').forEach(img => { if (!imageControls.has(img) && img.offsetWidth > 0 && img.offsetHeight > 0) { images.push(img); } }); return images; }; let imgHiden = function() { const images = findAllImages(); images.forEach(img => { createImageControlButton(img); }); // 更新所有位置并清理孤立的控制元素 updatePositions(); }; let imgShown = function() { imageControls.forEach((button, img) => { img.style.visibility = 'visible'; img.style.filter = 'none'; if (button.parentNode) { button.parentNode.removeChild(button); } }); imageOutlines.forEach((outline) => { if (outline.parentNode) { outline.parentNode.removeChild(outline); } }); mouseTimers.forEach(timer => clearTimeout(timer)); mouseTimers.clear(); imageControls.clear(); imageOutlines.clear(); }; // 启动位置更新监听 let startPositionUpdates = function() { // 监听滚动 window.addEventListener('scroll', updatePositions, { passive: true }); // 监听窗口大小变化 window.addEventListener('resize', updatePositions, { passive: true }); // 监听图片加载 document.addEventListener('load', function(e) { if (e.target.tagName === 'IMG') { setTimeout(updatePositions, 100); } }, true); }; let handleButtonClick = function() { if (window.imgHidenSet === null) { clearInterval(window.imgShownSet); window.imgShownSet = null; startPositionUpdates(); imgHiden(); saveStorageList(); window.imgHidenSet = setInterval(imgHiden, 500); } else { clearInterval(window.imgHidenSet); window.imgHidenSet = null; imgShown(); deleteStorageList(); window.imgShownSet = setInterval(imgShown, 500); } }; let noDetectStorageList = function() { if (localStorage.getItem('nopicValueList') !== null) { let valueList = localStorage.getItem('nopicValueList').split(','); if (valueList.indexOf(location.host) === -1) return true; } else { localStorage.setItem('nopicValueList', ['fxalll']); return true; } return false; }; let saveStorageList = function() { if (noDetectStorageList()) { let valueList = localStorage.getItem('nopicValueList').split(','); if (!valueList.includes(location.host)) { valueList.push(location.host); localStorage.setItem('nopicValueList', valueList); } } }; let deleteStorageList = function() { if (!noDetectStorageList()) { let valueList = localStorage.getItem('nopicValueList').split(','); valueList = valueList.filter(value => value !== location.host); localStorage.setItem('nopicValueList', valueList); } }; // 初始化 if (!noDetectStorageList()) { startPositionUpdates(); imgHiden(); window.imgHidenSet = setInterval(imgHiden, 500); } let button = document.createElement('div'); button.innerText = "◀"; button.setAttribute("id", "myButton"); button.style.color = "#555"; button.style.padding = "10px 15px"; button.style.position = "fixed"; button.style.top = "50%"; button.style.left = "3px"; button.style.textAlign = "center"; button.style.alignContent = "center"; button.style.background = "rgba(128, 128, 128, 0.4)"; button.style.borderRadius = "15px"; button.style.border = "2px solid rgba(128, 128, 128, 0.7)"; button.style.cursor = "pointer"; button.style.transform = "translate3d(30%,0,0)"; button.style.transition = "all 0.1s ease, backdrop-filter 0.4s ease, background 0.4s ease, box-shadow 0.4s ease, opacity 0.4s ease"; button.style.backdropFilter = "blur(15px) saturate(1.2)"; button.style.webkitBackdropFilter = "blur(15px) saturate(1.2)"; button.style.userSelect = "none"; button.style.zIndex = "999999999999"; button.addEventListener('mouseover', mouseover); button.addEventListener('mouseout', mouseout); button.addEventListener('mousedown', dragStart, false); function mouseover() { button.style.boxShadow = "0 0 20px rgba(128, 128, 128, 0.8)"; button.style.background = "rgba(160, 160, 160, 0.8)"; button.style.color = "#fff"; button.style.border = "2px solid rgba(200, 200, 200, 1)"; button.style.backdropFilter = "blur(20px) saturate(1.5)"; button.style.webkitBackdropFilter = "blur(20px) saturate(1.5)"; button.innerText = "图片显隐"; button.style.transform = "translateX(0px)"; setTranslate(0+"%",currentY+"px",button); } function mouseout() { button.style.boxShadow = ''; button.style.background = "rgba(128, 128, 128, 0.3)"; button.style.color = "#555"; button.style.border = "2px solid rgba(128, 128, 128, 0.6)"; button.style.backdropFilter = "blur(15px) saturate(1.2)"; button.style.webkitBackdropFilter = "blur(15px) saturate(1.2)"; button.innerText = "◀"; button.style.transform = "translateX(30%)"; setTranslate(30+"%",currentY+"px",button); } function dragStart(e) { startTime = e.timeStamp; initialX = e.clientX; initialY = e.clientY - yOffset; document.addEventListener('mousemove', drag); document.addEventListener('mouseup', dragEnd, false); e.preventDefault(); randomNumSet = Math.round(Math.random()*(yanEmoji.length-1)); } function dragEnd(e) { if (startTime) { let diffTime = e.timeStamp - startTime; diffTime < 150 && handleButtonClick(); startTime = 0; } initialX = currentX; initialY = currentY; mouseout(); document.removeEventListener('mousemove', drag); } function drag(e) { changeFace(randomNumSet,button); button.style.color = "#fff"; button.style.border = "4px dashed rgba(128, 128, 128, 0.8)"; button.style.background = "rgba(100, 100, 100, 0.6)"; button.style.backdropFilter = "blur(25px) saturate(1.8)"; button.style.webkitBackdropFilter = "blur(25px) saturate(1.8)"; e.preventDefault(); currentX = e.clientX - initialX; currentY = e.clientY - initialY; xOffset = currentX; yOffset = currentY; setTranslate(currentX+"px", currentY+"px", button); } function setTranslate(xPos, yPos, el) { el.style.transform = "translate3d(" + xPos + ", " + yPos + ", 0)"; } function changeFace(randomNum,el) { el.innerText = yanEmoji[randomNum]; } document.body.appendChild(button); })();