您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
鼠标悬停到图片上时自动放大,预览!
// ==UserScript== // @name 馒头种子列表页图片预览 // @namespace http://tampermonkey.net/ // @version 1.0 // @description 鼠标悬停到图片上时自动放大,预览! // @author ShaoxiongXu // @match https://*.m-team.cc/* // @match https://*.m-team.io/* // @match https://test2.m-team.cc/* // @grant GM_addStyle // @grant unsafeWindow // @run-at document-start // @license GPL-2.0 // ==/UserScript== (function () { 'use strict'; let i = 0; // MutationObserver 实例 let observer = undefined; function setStyle(link) { link.addEventListener("click", function () { this.querySelector("strong").style.color = '#70ada7' }) } function addEven(thumbnail) { let parent = thumbnail.parentElement let removeIcon = parent.querySelector("div") if (removeIcon) parent.removeChild(removeIcon) let imgPreview = document.querySelector("#img-preview") parent.addEventListener('mouseover', function (e) { let flagElement = this.parentElement; let img = this.querySelector("img"); let src = img.src if (src) { imgPreview.src = src; // 视窗 const viewportWidth = window.innerWidth; const viewportHeight = window.innerHeight; // 略缩图片相对于视窗的位置 const imgPosition = flagElement.getBoundingClientRect(); const imgLeft = imgPosition.x; // const imgTop = imgPosition.y; const imgWidth = imgPosition.width; // const imgHeight = imgPosition.height; // 图片的真实宽度 (自由放大的宽度) let imgNaturalWidth = img.naturalWidth let imgNaturalHeight = img.naturalHeight // 宽高比 let ratio = imgNaturalWidth / imgNaturalHeight; // 计算出可以显示图片的最大区域, 视口宽 - (imgLeft + imgWidth + 10) * 2 ,去掉两边只剩中间区域 let maxImgWidth = viewportWidth - (imgLeft + imgWidth + 10) * 2 imgPreview.style.maxWidth = `${maxImgWidth}px`; // 判断高度是否够 目前设定最大高度为视窗 80% let maxImgHeight = viewportHeight * 0.8; // 在高度不限制下的图片宽度,如果高度不够宽度会压缩 let previewImgWidth = imgNaturalWidth > maxImgWidth ? maxImgWidth : imgNaturalWidth; console.log("预览图宽度:", previewImgWidth) // 计算显示高度,如果宽度压缩了高度也会压缩 let previewImgHeight = previewImgWidth / ratio; if (previewImgHeight > maxImgHeight) { previewImgHeight = previewImgHeight > maxImgHeight ? maxImgHeight : previewImgHeight // 压缩比率 * 图片实际宽度 previewImgWidth = (imgNaturalWidth / imgNaturalHeight) * previewImgHeight } console.log("预览图宽度:", previewImgWidth) // 还有空间,尝试放大图片 最大放大2倍 let enlargementFactor = Math.min(maxImgWidth / previewImgWidth, maxImgHeight / previewImgHeight) if (enlargementFactor > 2) enlargementFactor = 2; console.log("放大倍数:", enlargementFactor) imgPreview.style.width = `${previewImgWidth * enlargementFactor}px`; imgPreview.style.left = `calc(50% - ${previewImgWidth * enlargementFactor / 2}px)`; // 显示预览 imgPreview.style.display = 'block'; } }); parent.addEventListener('mouseout', function (e) { console.log("鼠标移开图片时触发") // 隐藏预览 imgPreview.style.display = 'none'; }); } function exec(arr) { if (!observer) { observer = new MutationObserver(function (mutationsList, observer) { // 遍历每一个发生变化的 mutation mutationsList.forEach(function (mutation) { // 检查每一个新添加的节点 mutation.addedNodes.forEach(function (node) { if (node instanceof HTMLElement) { node.querySelectorAll('a[href^="/detail"]').forEach(function (link) { // console.log("新增的a标签:", link) console.log("新增的a标签计数:", i++) setStyle(link); }); node.querySelectorAll(".torrent-list__thumbnail").forEach((thumbnail) => { addEven(thumbnail); }) } }); }); }); // 配置 MutationObserver 监听目标以及要观察的子节点 observer.observe(document.querySelector("#root"), {childList: true, subtree: true}); } } function init() { console.log("init...") const originOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function (_, url) { if (url.includes("/api/torrent/search")) { this.addEventListener("readystatechange", function () { if (this.readyState === 4 && this.status === 200) { const res = JSON.parse(this.responseText); if (res.message === "SUCCESS") { exec(res.data.data); } } }); } originOpen.apply(this, arguments); } GM_addStyle(` #img-preview { position: fixed; display: none; max-height: 80%; top: 50%; transform: translateY(-50%); z-index: 999; } `); } function appendImgElement() { let img = document.createElement('img') img.setAttribute('id', 'img-preview'); document.body.append(img) } let isLoad = false; if (window.location.pathname.startsWith("/browse")) { console.log("加载列表页油猴脚本...") isLoad = true; init(); if (document.readyState === "loading") { // 在DOM加载完成后执行的代码,页面资源加载可能仍在进行中,但DOM已准备就绪 document.addEventListener('DOMContentLoaded', function () { // 单独配置了的站点或者 NexusPHP 站点 console.log("img preview 在DOM加载完成后执行...") appendImgElement(); }, {once: true}); } else { // `DOMContentLoaded` 已经被触发 极低概率触发。。。 console.log("img preview DOMContentLoaded 已经被触发") appendImgElement(); } } let originPush = history.pushState; history.pushState = function (...arg) { if (!isLoad && arg[arg.length - 1].startsWith("/browse")) { isLoad = true; console.log("路由变化, 加载列表页油猴脚本..."); init(); appendImgElement(); } return originPush.call(this, ...arg); }; })();