Greasy Fork is available in English.
通过原生 UI 控制当前页面图片的显示和隐藏,支持持久化设置
// ==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
// ==/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 = '<span id="image-toggler-icon">👁️</span> <span id="image-toggler-text">显</span>';
el.classList.add('visible-mode');
el.title = '当前:图片显示。点击隐藏图片';
} else {
el.innerHTML = '<span id="image-toggler-icon">🚫</span> <span id="image-toggler-text">隐</span>';
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();
})();