Last active
November 21, 2025 07:09
-
-
Save engalar/5a8f2a401402acf0ace114a6f51c5ce1 to your computer and use it in GitHub Desktop.
网页元素截图工具
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name 网页元素截图工具 | |
| // @namespace http://tampermonkey.net/ | |
| // @version 1.2 | |
| // @description 直接利用 @require 加载库,解决 window.htmlToImage 为 undefined 的问题 | |
| // @author YourName | |
| // @match *://*/* | |
| // @grant GM_registerMenuCommand | |
| // @grant GM_addStyle | |
| // @require https://cdnjs.cloudflare.com/ajax/libs/html-to-image/1.11.11/html-to-image.min.js | |
| // @downloadURL https://gist.github.com/engalar/5a8f2a401402acf0ace114a6f51c5ce1/raw/snap.user.js | |
| // @run-at document-idle | |
| // ==/UserScript== | |
| (function() { | |
| 'use strict'; | |
| // ================================================================= | |
| // 1. 核心截图逻辑 (大幅简化) | |
| // ================================================================= | |
| const captureElement = async function (element, fileName) { | |
| try { | |
| // 检查库是否加载成功 (@require 会在脚本运行前加载它) | |
| // 注意:在 @require 模式下,库通常挂载在 window 或全局作用域下 | |
| // 如果网页有 define,油猴通常有机制隔离,或者库会挂载到 globalThis | |
| const lib = window.htmlToImage || htmlToImage; | |
| if (!lib) { | |
| throw new Error('html-to-image 库未找到,可能是 @require 加载失败'); | |
| } | |
| const toast = showToast('正在生成截图,请稍候...'); | |
| const config = { | |
| quality: 0.95, | |
| backgroundColor: '#ffffff', | |
| filter: (node) => (node.id !== 'tm-screenshot-toast') | |
| }; | |
| const dataUrl = await lib.toPng(element, config); | |
| const link = document.createElement('a'); | |
| link.download = fileName || `screenshot_${Date.now()}.png`; | |
| link.href = dataUrl; | |
| document.body.appendChild(link); | |
| link.click(); | |
| document.body.removeChild(link); | |
| toast.innerText = '截图成功!已开始下载'; | |
| setTimeout(() => toast.remove(), 2000); | |
| } catch (error) { | |
| console.error('截图失败:', error); | |
| showToast('截图失败: ' + error.message, true); | |
| } | |
| }; | |
| // ================================================================= | |
| // 2. 交互选择器逻辑 (保持不变) | |
| // ================================================================= | |
| let isSelecting = false; | |
| let currentHighlight = null; | |
| let highlightStyleElement = null; | |
| function activateSelector() { | |
| if (isSelecting) return; | |
| isSelecting = true; | |
| showToast('进入截图模式:请点击要截取的元素 (右键取消)'); | |
| const css = ` | |
| .tm-screenshot-highlight { | |
| outline: 4px solid #ff4757 !important; | |
| outline-offset: -4px !important; | |
| cursor: crosshair !important; | |
| transition: all 0.1s; | |
| } | |
| `; | |
| highlightStyleElement = GM_addStyle(css); | |
| document.addEventListener('mouseover', onMouseOver, true); | |
| document.addEventListener('mouseout', onMouseOut, true); | |
| document.addEventListener('click', onClick, true); | |
| document.addEventListener('contextmenu', onCancel, true); | |
| } | |
| function cleanup() { | |
| isSelecting = false; | |
| if (currentHighlight) { | |
| currentHighlight.classList.remove('tm-screenshot-highlight'); | |
| currentHighlight = null; | |
| } | |
| if (highlightStyleElement) { | |
| highlightStyleElement.remove(); | |
| highlightStyleElement = null; | |
| } | |
| document.removeEventListener('mouseover', onMouseOver, true); | |
| document.removeEventListener('mouseout', onMouseOut, true); | |
| document.removeEventListener('click', onClick, true); | |
| document.removeEventListener('contextmenu', onCancel, true); | |
| } | |
| function onMouseOver(e) { | |
| if (!isSelecting) return; | |
| e.stopPropagation(); | |
| if(e.target.id === 'tm-screenshot-toast') return; | |
| if (currentHighlight && currentHighlight !== e.target) { | |
| currentHighlight.classList.remove('tm-screenshot-highlight'); | |
| } | |
| currentHighlight = e.target; | |
| currentHighlight.classList.add('tm-screenshot-highlight'); | |
| } | |
| function onMouseOut(e) { | |
| if (!isSelecting) return; | |
| if (e.target === currentHighlight) { | |
| e.target.classList.remove('tm-screenshot-highlight'); | |
| currentHighlight = null; | |
| } | |
| } | |
| function onClick(e) { | |
| if (!isSelecting) return; | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| const target = e.target; | |
| target.classList.remove('tm-screenshot-highlight'); | |
| captureElement(target); | |
| cleanup(); | |
| } | |
| function onCancel(e) { | |
| if (!isSelecting) return; | |
| e.preventDefault(); | |
| showToast('已取消截图'); | |
| cleanup(); | |
| } | |
| function showToast(text, isError = false) { | |
| let toast = document.getElementById('tm-screenshot-toast'); | |
| if (!toast) { | |
| toast = document.createElement('div'); | |
| toast.id = 'tm-screenshot-toast'; | |
| Object.assign(toast.style, { | |
| position: 'fixed', | |
| top: '20px', | |
| left: '50%', | |
| transform: 'translateX(-50%)', | |
| padding: '10px 20px', | |
| borderRadius: '5px', | |
| color: '#fff', | |
| fontSize: '14px', | |
| fontFamily: 'sans-serif', | |
| zIndex: '2147483647', | |
| pointerEvents: 'none', | |
| boxShadow: '0 2px 10px rgba(0,0,0,0.2)' | |
| }); | |
| document.body.appendChild(toast); | |
| } | |
| toast.style.backgroundColor = isError ? '#ff4757' : '#2ed573'; | |
| toast.innerText = text; | |
| return toast; | |
| } | |
| GM_registerMenuCommand("📷 截取指定元素", activateSelector); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment