// ==UserScript==
// @name Native Image Toggler
// @namespace http://tampermonkey.net/
// @version 0.2
// @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 hostname = window.location.hostname;
const storageKey = STORAGE_KEY_PREFIX + hostname;
// 状态:true 表示图片显示(默认),false 表示图片隐藏
// 默认所有网站都是显示的,除非用户手动关闭
let isImagesVisible = GM_getValue(storageKey, 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;
top: 10px;
right: 20px;
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: pointer;
user-select: none;
box-shadow: 0 4px 15px rgba(0,0,0,0.3);
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
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.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();
} else {
document.addEventListener('DOMContentLoaded', setupUI);
}
// 注册菜单命令作为备用
GM_registerMenuCommand("切换图片显示/隐藏", toggleImages);
}
function setupUI() {
// 防止重复创建
if (document.getElementById('image-toggler-ui')) return;
// 添加 UI 样式
GM_addStyle(uiCSS);
// 创建 UI
createUI();
}
// 创建 UI 控件
function createUI() {
const div = document.createElement('div');
div.id = 'image-toggler-ui';
div.title = '点击切换当前网站图片显示状态';
div.onclick = toggleImages;
document.body.appendChild(div);
updateUI(div);
}
// 更新 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();
}
// 应用状态(添加或移除 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();
})();