// ==UserScript== // @name 禁用电商平台图片缩放效果 (终极版) // @name:en Disable E-commerce Image Zoom Effect (Ultimate) // @namespace https://greasyfork.org/users/3001-hanjian-wu // @version 1.6.0 // @description 精准禁用淘宝、天猫、1688、京东等平台的图片放大镜(jqzoom)效果,方便右键。采用多重防御策略,彻底解决问题。 // @description:en Precisely disable image magnifier (jqzoom) on Taobao, Tmall, 1688, JD. Uses a multi-layered defense strategy for a complete fix. // @author hanjian wu (Enhanced by AI) // @homepage https://greasyfork.org/users/3001-hanjian-wu // @license MIT // @match *://*.taobao.com/item.htm* // @match *://*.tmall.com/item.htm* // @match *://*.1688.com/offer/*.html* // @match *://item.taobao.com/* // @match *://detail.tmall.com/* // @match *://detail.1688.com/* // @match *://item.jd.com/* // @match *://*.jd.com/product/* // @grant none // @run-at document-start // @noframes // @downloadURL none // ==/UserScript== (function() { 'use strict'; console.log('电商图片缩放禁用脚本 v1.6.0 (多重防御策略)'); // --- 第一道防线:CSS 隐藏 --- // 尽早注入CSS,直接隐藏 jqzoom 创建的元素,这是最高效的方式。 const style = document.createElement('style'); style.id = 'disable-zoom-styles-ultimate'; style.textContent = ` /* 根据你捕获的HTML,精准隐藏jqzoom的动态元素 */ .jqZoomPup, /* 放大镜方块 */ .zoomdiv, /* 放大后图片的容器 */ .jqzoom-window /* jqzoom可能的另一种容器类名 */ { display: none !important; visibility: hidden !important; opacity: 0 !important; pointer-events: none !important; position: absolute !important; top: -99999px !important; left: -99999px !important; } /* 确保主图本身可交互 */ #spec-n1, #spec-img { cursor: default !important; } `; (document.head || document.documentElement).appendChild(style); console.log('[防御1] CSS规则已注入,隐藏jqzoom动态元素。'); // --- 第二道防线:重写 jQuery 插件 --- // 多数情况下,jqzoom是jQuery插件。我们在它执行前,把它定义为空函数。 // 这需要持续检测 jQuery 是否已加载。 function neutralizeJqzoomPlugin() { // 检查jQuery和jqzoom插件是否已存在于window对象 if (typeof window.jQuery !== 'undefined' && typeof window.jQuery.fn.jqzoom !== 'undefined') { window.jQuery.fn.jqzoom = function() { console.log('[防御2] jqzoom() 已被禁用,调用无效。'); return this; // 维持jQuery的链式调用 }; // 成功禁用后,可以停止定时器 if (jqzoomCheckInterval) { clearInterval(jqzoomCheckInterval); console.log('[防御2] 成功禁用jqzoom插件,停止检测。'); } } } // 因为不确定jQuery何时加载,所以设置一个定时器持续检查 const jqzoomCheckInterval = setInterval(neutralizeJqzoomPlugin, 100); // 页面加载完成后,如果还没禁用,再尝试一次 window.addEventListener('load', () => { neutralizeJqzoomPlugin(); // 如果5秒后还没禁用成功,就不再浪费资源了 setTimeout(() => clearInterval(jqzoomCheckInterval), 5000); }); // --- 第三道防线:阻止事件传播 --- // 作为终极保险,直接在容器上捕获并阻止鼠标事件传播。 function blockHoverEvents(container) { if (!container || container.dataset.eventsBlocked) return; const eventsToBlock = ['mouseenter', 'mouseover', 'mousemove']; eventsToBlock.forEach(eventType => { container.addEventListener(eventType, (e) => { e.stopImmediatePropagation(); // 阻止后续任何同类事件的监听器执行 }, { capture: true }); // 使用捕获模式,确保我们的监听器最先执行 }); container.dataset.eventsBlocked = 'true'; console.log(`[防御3] 已在元素 #${container.id} 上阻止鼠标悬停事件。`); } // --- 执行与监控 --- // 使用 MutationObserver 监控DOM变化,以应对异步加载的图片廊。 const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { for (const node of mutation.addedNodes) { if (node.nodeType === 1) { // 确保是元素节点 // 查找目标容器 const zoomContainer = node.matches('#spec-n1, .jqzoom') ? node : node.querySelector('#spec-n1, .jqzoom'); if (zoomContainer) { blockHoverEvents(zoomContainer); // 找到了就可以停止观察,或者根据需要继续 // observer.disconnect(); } } } } }); // 等待DOM加载完成后开始观察 document.addEventListener('DOMContentLoaded', () => { const initialContainer = document.querySelector('#spec-n1, .jqzoom'); if (initialContainer) { blockHoverEvents(initialContainer); } observer.observe(document.body, { childList: true, subtree: true }); }); })();