您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在手机上长按一个元素,会弹出一个菜单来屏蔽它。可以记住你的选择。
// ==UserScript== // @name Website Element Blocker (Long-press to block) // @name:zh-CN 网页元素屏蔽器 (长按屏蔽) // @namespace http://tampermonkey.net/ // @version 1.6 // @description Long-press on an element on your phone to bring up a menu to block it. Remembers your choices. // @description:zh-CN 在手机上长按一个元素,会弹出一个菜单来屏蔽它。可以记住你的选择。 // @author Your AI Assistant // @match *://*/* // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_addStyle // ==/UserScript== (function() { 'use strict'; // --- 配置 --- const LONG_PRESS_DURATION = 500; // 长按时长 (毫秒) const STORAGE_KEY_PREFIX = 'element_blocker_'; let pressTimer = null; let longPressFired = false; let targetElement = null; let highlightElements = []; // --- 样式注入 --- GM_addStyle(` .blocker-highlight-wrapper { position: relative !important; z-index: 2147483646 !important; } .blocker-highlight-border { position: absolute; background: linear-gradient(90deg, rgba(255, 0, 0, 0.8) 0%, rgba(255, 127, 0, 0.8) 25%, rgba(255, 255, 0, 0.8) 50%, rgba(0, 255, 0, 0.8) 75%, rgba(0, 0, 255, 0.8) 100%); animation: blocker-rainbow 2s linear infinite; z-index: 2147483645; pointer-events: none; } .blocker-highlight-top { top: -4px; left: 0; right: 0; height: 4px; } .blocker-highlight-right { top: 0; right: -4px; bottom: 0; width: 4px; } .blocker-highlight-bottom { bottom: -4px; left: 0; right: 0; height: 4px; } .blocker-highlight-left { top: 0; left: -4px; bottom: 0; width: 4px; } @keyframes blocker-rainbow { 0% { background-position: 0% 50%; } 100% { background-position: 100% 50%; } } #blocker-menu { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background-color: #333; color: white; padding: 10px; border-radius: 8px; z-index: 2147483647 !important; display: flex; flex-direction: column; gap: 8px; box-shadow: 0 4px 15px rgba(0,0,0,0.4); font-family: sans-serif; font-size: 16px; } #blocker-menu button { background-color: #555; color: white; border: none; padding: 10px 15px; border-radius: 5px; cursor: pointer; text-align: center; } #blocker-menu button:hover { background-color: #777; } `); // --- 核心功能 --- function getCssSelector(el) { if (!(el instanceof Element)) return; const path = []; while (el.nodeType === Node.ELEMENT_NODE) { let selector = el.nodeName.toLowerCase(); if (el.id) { selector += `#${el.id}`; path.unshift(selector); break; } else { let sib = el, nth = 1; while (sib.previousElementSibling) { sib = sib.previousElementSibling; if (sib.nodeName.toLowerCase() == selector) nth++; } if (nth != 1) selector += `:nth-of-type(${nth})`; } path.unshift(selector); el = el.parentNode; } return path.join(' > '); } function createHighlightBorder(className) { const border = document.createElement('div'); border.className = `blocker-highlight-border ${className}`; return border; } function highlightElement(el) { unhighlightAll(); if (!el) return; // 创建一个包装元素来包含边框 const wrapper = document.createElement('div'); wrapper.className = 'blocker-highlight-wrapper'; // 保存原始元素的样式和位置 const originalStyle = el.getAttribute('style') || ''; const originalPosition = window.getComputedStyle(el).position; // 确保元素有相对定位以便边框正确放置 if (originalPosition === 'static') { el.style.position = 'relative'; } // 添加四个边框 wrapper.appendChild(createHighlightBorder('blocker-highlight-top')); wrapper.appendChild(createHighlightBorder('blocker-highlight-right')); wrapper.appendChild(createHighlightBorder('blocker-highlight-bottom')); wrapper.appendChild(createHighlightBorder('blocker-highlight-left')); // 用包装元素包裹原始元素 el.parentNode.insertBefore(wrapper, el); wrapper.appendChild(el); // 保存引用以便之后移除 highlightElements.push({ wrapper: wrapper, originalStyle: originalStyle, originalPosition: originalPosition, element: el }); } function unhighlightAll() { highlightElements.forEach(item => { // 恢复原始元素的样式和位置 if (item.originalPosition === 'static') { item.element.style.position = ''; } item.element.setAttribute('style', item.originalStyle); // 将元素放回原处并移除包装 item.wrapper.parentNode.insertBefore(item.element, item.wrapper); item.wrapper.remove(); }); highlightElements = []; } function showBlockMenu(el) { // 移除旧菜单 const oldMenu = document.getElementById('blocker-menu'); if (oldMenu) oldMenu.remove(); const menu = document.createElement('div'); menu.id = 'blocker-menu'; let currentEl = el; let level = 0; const createButton = (elem, text) => { const button = document.createElement('button'); button.textContent = text; button.onclick = (e) => { e.stopPropagation(); blockElement(elem); hideBlockMenu(); }; button.onmouseover = () => highlightElement(elem); button.onmouseout = () => highlightElement(targetElement); return button; }; // 添加 "屏蔽当前" 按钮 menu.appendChild(createButton(currentEl, `屏蔽当前 (${currentEl.tagName.toLowerCase()})`)); // 添加 "屏蔽上层" 按钮 (最多5层) while (currentEl.parentElement && level < 5) { currentEl = currentEl.parentElement; if (currentEl.tagName.toLowerCase() === 'body' || currentEl.tagName.toLowerCase() === 'html') break; level++; menu.appendChild(createButton(currentEl, `屏蔽上${level}层 (${currentEl.tagName.toLowerCase()})`)); } const cancelButton = document.createElement('button'); cancelButton.textContent = '取消'; cancelButton.style.backgroundColor = '#800'; cancelButton.onclick = hideBlockMenu; menu.appendChild(cancelButton); document.body.appendChild(menu); highlightElement(el); } function hideBlockMenu() { const menu = document.getElementById('blocker-menu'); if (menu) menu.remove(); unhighlightAll(); } function blockElement(el) { const selector = getCssSelector(el); if (!selector) return; const hostname = window.location.hostname; const key = STORAGE_KEY_PREFIX + hostname; const blockedSelectors = GM_getValue(key, []); if (!blockedSelectors.includes(selector)) { blockedSelectors.push(selector); GM_setValue(key, blockedSelectors); applyBlocking(hostname); console.log(`[Element Blocker] 已屏蔽: ${selector}`); } } function applyBlocking(hostname) { const key = STORAGE_KEY_PREFIX + hostname; const selectors = GM_getValue(key, []); if (selectors.length > 0) { let style = document.getElementById('dynamic-blocker-style'); if (!style) { style = document.createElement('style'); style.id = 'dynamic-blocker-style'; document.head.appendChild(style); } style.textContent = `${selectors.join(', ')} { display: none !important; }`; console.log(`[Element Blocker] 已应用 ${selectors.length} 条屏蔽规则于 ${hostname}`); } } function clearBlockingRules() { const hostname = window.location.hostname; const key = STORAGE_KEY_PREFIX + hostname; GM_setValue(key, []); const style = document.getElementById('dynamic-blocker-style'); if (style) style.textContent = ''; alert(`已清除网站 [${hostname}] 的所有屏蔽规则。`); } // --- 事件监听 --- function onTouchStart(e) { if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.isContentEditable) { return; } longPressFired = false; targetElement = e.target; pressTimer = window.setTimeout(() => { longPressFired = true; e.preventDefault(); showBlockMenu(targetElement); }, LONG_PRESS_DURATION); } function onTouchEnd(e) { clearTimeout(pressTimer); } function onTouchMove(e) { clearTimeout(pressTimer); } // 绑定事件 window.addEventListener('touchstart', onTouchStart, { passive: false }); window.addEventListener('touchend', onTouchEnd); window.addEventListener('touchmove', onTouchMove); // --- 页面加载时应用规则 & 注册菜单 --- applyBlocking(window.location.hostname); GM_registerMenuCommand('清除当前网站的屏蔽规则', clearBlockingRules); })();