// ==UserScript== // @name Native Image Toggler // @namespace http://tampermonkey.net/ // @version 0.3 // @description 通过原生 UI 控制当前页面图片的显示和隐藏,支持持久化设置 // @author You // @match *://*/* // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_addStyle // @run-at document-start // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 配置常量 const STORAGE_KEY_PREFIX = 'img_toggle_'; const STYLE_ID = 'native-image-toggler-style'; const POSITION_KEY = 'img_toggle_position_'; const UI_VISIBLE_KEY = 'img_toggle_ui_visible_'; const DEFAULT_POSITION = { top: 10, right: 20 }; // 获取当前域名的设置键 const hostname = window.location.hostname; const storageKey = STORAGE_KEY_PREFIX + hostname; const positionKey = POSITION_KEY + hostname; // 状态:true 表示图片显示(默认),false 表示图片隐藏 // 默认所有网站都是显示的,除非用户手动关闭 let isImagesVisible = GM_getValue(storageKey, true); let uiPosition = GM_getValue(positionKey, DEFAULT_POSITION); let isUIVisible = GM_getValue(UI_VISIBLE_KEY, true); // CSS 样式:隐藏图片的样式 const hideImageCSS = ` img, image, picture, svg, canvas, video, iframe { opacity: 0 !important; visibility: hidden !important; pointer-events: none !important; } * { background-image: none !important; } /* 排除我们自己的 UI */ #image-toggler-ui, #image-toggler-ui * { opacity: 1 !important; visibility: visible !important; pointer-events: auto !important; background-image: initial !important; } `; // CSS 样式:UI 控件的样式 const uiCSS = ` #image-toggler-ui { position: fixed; z-index: 2147483647; /* Max Z-Index */ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background-color: rgba(30, 30, 30, 0.8); backdrop-filter: blur(10px); color: #fff; padding: 8px; border-radius: 16px; cursor: grab; user-select: none; box-shadow: 0 4px 15px rgba(0,0,0,0.3); transition: transform 0.2s ease, box-shadow 0.2s ease; font-size: 14px; font-weight: 500; display: flex; align-items: center; gap: 8px; border: 1px solid rgba(255, 255, 255, 0.1); opacity: 0.9; } #image-toggler-ui:hover { opacity: 1; transform: translateY(2px); box-shadow: 0 6px 20px rgba(0,0,0,0.4); } #image-toggler-ui.dragging { cursor: grabbing; box-shadow: 0 8px 25px rgba(0,0,0,0.5); transform: scale(1.05); z-index: 2147483647; } #image-toggler-ui.hidden-mode { background-color: rgba(69, 105, 212, 0.9); border-color: rgba(69, 105, 212, 0.5); } #image-toggler-ui.visible-mode { background-color: rgba(69, 105, 212, 0.9); border-color: rgba(69, 105, 212, 0.5); } #image-toggler-icon { font-size: 16px; line-height: 1; } #image-toggler-text { line-height: 1; } `; // 初始化 function init() { // 尽早应用状态(如果需要隐藏图片) applyState(); // 等待 body 加载完成后创建 UI if (document.body) { setupUI(); applyUIState(); } else { document.addEventListener('DOMContentLoaded', setupUI); document.addEventListener('DOMContentLoaded', applyUIState); } // 注册菜单命令作为备用 GM_registerMenuCommand("切换图片显示/隐藏", toggleImages); GM_registerMenuCommand("切换控件显示/隐藏", toggleUIVisibility); // 添加键盘快捷键 Ctrl+Shift+I document.addEventListener('keydown', function(e) { if (e.ctrlKey && e.shiftKey && e.key === 'I') { e.preventDefault(); toggleImages(); } }); } function setupUI() { // 防止重复创建 if (document.getElementById('image-toggler-ui') && document.getElementById('image-toggler-ui-top')) return; // 添加 UI 样式 GM_addStyle(uiCSS); // 创建 UI createUI(); } // 创建 UI 控件 function createUI() { const div = document.createElement('div'); div.id = 'image-toggler-ui'; div.style.top = uiPosition.top + 'px'; div.style.right = uiPosition.right + 'px'; let isDragging = false; let dragOffsetX = 0; let dragOffsetY = 0; div.addEventListener('mousedown', function(e) { if (e.button !== 0) return; const rect = div.getBoundingClientRect(); dragOffsetX = e.clientX - rect.left; dragOffsetY = e.clientY - rect.top; isDragging = true; div.classList.add('dragging'); e.preventDefault(); }); document.addEventListener('mousemove', function(e) { if (!isDragging) return; const newLeft = e.clientX - dragOffsetX; const newTop = e.clientY - dragOffsetY; div.style.right = 'auto'; div.style.left = newLeft + 'px'; div.style.top = newTop + 'px'; }); document.addEventListener('mouseup', function(e) { if (!isDragging) return; isDragging = false; div.classList.remove('dragging'); const rect = div.getBoundingClientRect(); const finalLeft = rect.left; const finalTop = rect.top; uiPosition = { top: finalTop, right: window.innerWidth - finalLeft - rect.width }; GM_setValue(positionKey, uiPosition); div.style.left = 'auto'; div.style.right = uiPosition.right + 'px'; }); div.addEventListener('click', function(e) { if (isDragging) { e.preventDefault(); e.stopPropagation(); return; } toggleImages(); }); div.title = '拖动调整位置 | 点击切换图片显隐 | Ctrl+Shift+I 快捷键切换'; document.body.appendChild(div); updateUI(div); // 创建右上角 UI } // 更新 UI 显示 function updateUI(element) { const el = element || document.getElementById('image-toggler-ui'); if (!el) return; // 移除旧的类 el.classList.remove('visible-mode', 'hidden-mode'); if (isImagesVisible) { el.innerHTML = '👁️ '; el.classList.add('visible-mode'); el.title = '当前:图片显示。点击隐藏图片'; } else { el.innerHTML = '🚫 '; el.classList.add('hidden-mode'); el.title = '当前:图片隐藏。点击显示图片'; } // 不需要在这里直接设置 backgroundColor,交由 CSS 类处理 el.style.backgroundColor = ''; } // 切换状态 function toggleImages() { isImagesVisible = !isImagesVisible; GM_setValue(storageKey, isImagesVisible); applyState(); updateUI(); } // 切换 UI 可见性 function toggleUIVisibility() { isUIVisible = !isUIVisible; GM_setValue(UI_VISIBLE_KEY, isUIVisible); applyUIState(); } // 应用 UI 可见性状态 function applyUIState() { const ui = document.getElementById('image-toggler-ui'); if (ui) { ui.style.display = isUIVisible ? 'flex' : 'none'; } } // 应用状态(添加或移除 CSS) function applyState() { let styleEl = document.getElementById(STYLE_ID); // 确保 head 存在,通常在 document-start 时 head 也是存在的(除了极早的情况) // 如果 head 不存在,稍微延时重试 if (!document.head) { setTimeout(applyState, 10); return; } if (!isImagesVisible) { // 如果需要隐藏图片,且样式元素不存在,则添加 if (!styleEl) { styleEl = document.createElement('style'); styleEl.id = STYLE_ID; styleEl.textContent = hideImageCSS; document.head.appendChild(styleEl); } } else { // 如果需要显示图片,且样式元素存在,则移除 if (styleEl) { styleEl.remove(); } } } // 启动 init(); })();