// ==UserScript==
// @name 网页截图(元素层级截图工具)
// @namespace http://tampermonkey.net/
// @version 0.1
// @description 网页内容元素级选择,可以进行编辑
// @author wilsend
// @match *://*/*
// @grant GM_registerMenuCommand
// @require https://html2canvas.hertzen.com/dist/html2canvas.min.js
// ==/UserScript==
(function() {
'use strict';
// 全局变量存储UI元素引用
let uiContainer = null;
let closeButton = null;
let elementInput = null;
let inputConfirmBtn = null;
// 编辑窗口相关变量
let editWindow = null;
let editContentContainer = null;
let removeElemBtn = null;
let saveEditBtn = null;
let cancelEditBtn = null;
let isEditing = false;
let isRemovingElem = false;
let editHighlight = null;
// 存储编辑时的元素副本和原始元素
let editedElementClone = null;
let originalSelectedElement = null;
// 存储页面原始样式表(用于保留样式)
let originalStylesheets = [];
// 创建操作界面元素
function createUI() {
if (document.getElementById('element-screenshot-tool')) {
uiContainer = document.getElementById('element-screenshot-tool');
closeButton = uiContainer.querySelector('#close-btn');
elementInput = uiContainer.querySelector('#element-input');
inputConfirmBtn = uiContainer.querySelector('#input-confirm-btn');
return uiContainer;
}
// 主容器
const container = document.createElement('div');
container.id = 'element-screenshot-tool';
container.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
z-index: 999999;
background: white;
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 15px rgba(0,0,0,0.2);
max-width: 300px;
font-family: Arial, sans-serif;
`;
// 标题
const title = document.createElement('h3');
title.textContent = '任意元素截图工具';
title.style.marginTop = '0';
title.style.color = '#333';
// 状态显示
const status = document.createElement('div');
status.id = 'screenshot-status';
status.textContent = '请选择一个操作';
status.style.padding = '8px 0';
status.style.color = '#666';
status.style.fontSize = '14px';
// 手动输入元素区域
const inputArea = document.createElement('div');
inputArea.style.cssText = 'margin: 10px 0; display: flex; gap: 8px;';
const inputLabel = document.createElement('label');
inputLabel.textContent = '手动输入元素:';
inputLabel.style.fontSize = '12px';
inputLabel.style.alignSelf = 'center';
elementInput = document.createElement('input');
elementInput.id = 'element-input';
elementInput.type = 'text';
elementInput.placeholder = '标签名或#ID(例:div、#header)';
elementInput.style.flex = '1';
elementInput.style.padding = '6px';
elementInput.style.border = '1px solid #ddd';
elementInput.style.borderRadius = '4px';
elementInput.style.fontSize = '12px';
inputConfirmBtn = document.createElement('button');
inputConfirmBtn.id = 'input-confirm-btn';
inputConfirmBtn.textContent = '确认';
inputConfirmBtn.style.padding = '6px 12px';
inputConfirmBtn.style.backgroundColor = '#4285f4';
inputConfirmBtn.style.color = 'white';
inputConfirmBtn.style.border = 'none';
inputConfirmBtn.style.borderRadius = '4px';
inputConfirmBtn.style.cursor = 'pointer';
inputConfirmBtn.style.fontSize = '12px';
inputArea.appendChild(inputLabel);
inputArea.appendChild(elementInput);
inputArea.appendChild(inputConfirmBtn);
// 操作提示
const hint = document.createElement('div');
hint.style.cssText = `
font-size: 12px;
color: #888;
margin: 10px 0;
padding: 5px;
background: #f5f5f4;
border-radius: 4px;
`;
hint.innerHTML = '操作提示:
[ 扩大选择(父级)
] 缩小选择(子级)
回车/点击确认 | ESC取消';
// 按钮容器
const buttonContainer = document.createElement('div');
buttonContainer.style.display = 'flex';
buttonContainer.style.gap = '8px';
buttonContainer.style.marginBottom = '10px';
const selectButton = document.createElement('button');
selectButton.textContent = '鼠标选择元素';
selectButton.style.flex = '1';
selectButton.style.padding = '8px';
selectButton.style.backgroundColor = '#4285f4';
selectButton.style.color = 'white';
selectButton.style.border = 'none';
selectButton.style.borderRadius = '4px';
selectButton.style.cursor = 'pointer';
selectButton.id = 'select-element-button';
const editButton = document.createElement('button');
editButton.textContent = '编辑元素';
editButton.id = 'edit-element-button';
editButton.style.flex = '1';
editButton.style.padding = '8px';
editButton.style.backgroundColor = '#fbbc05';
editButton.style.color = 'white';
editButton.style.border = 'none';
editButton.style.borderRadius = '4px';
editButton.style.cursor = 'pointer';
editButton.disabled = true;
const captureButton = document.createElement('button');
captureButton.textContent = '保存截图';
captureButton.id = 'capture-button';
captureButton.style.flex = '1';
captureButton.style.padding = '8px';
captureButton.style.backgroundColor = '#34a853';
captureButton.style.color = 'white';
captureButton.style.border = 'none';
captureButton.style.borderRadius = '4px';
captureButton.style.cursor = 'pointer';
captureButton.disabled = true;
// 已选元素信息
const selectedInfo = document.createElement('div');
selectedInfo.id = 'selected-element-info';
selectedInfo.style.margin = '10px 0';
selectedInfo.style.padding = '8px';
selectedInfo.style.border = '1px dashed #ddd';
selectedInfo.style.borderRadius = '4px';
selectedInfo.style.fontSize = '12px';
selectedInfo.style.color = '#666';
selectedInfo.textContent = '未选择任何元素';
// 关闭按钮
const closeBtn = document.createElement('button');
closeBtn.id = 'close-btn';
closeBtn.textContent = '关闭';
closeBtn.style.width = '100%';
closeBtn.style.padding = '8px';
closeBtn.style.backgroundColor = '#ea4335';
closeBtn.style.color = 'white';
closeBtn.style.border = 'none';
closeBtn.style.borderRadius = '4px';
closeBtn.style.cursor = 'pointer';
// 组装界面
buttonContainer.appendChild(selectButton);
buttonContainer.appendChild(editButton);
buttonContainer.appendChild(captureButton);
container.appendChild(title);
container.appendChild(status);
container.appendChild(inputArea);
container.appendChild(hint);
container.appendChild(buttonContainer);
container.appendChild(selectedInfo);
container.appendChild(closeBtn);
document.body.appendChild(container);
// 更新全局引用
uiContainer = container;
closeButton = closeBtn;
return container;
}
// 创建全屏编辑窗口
function createEditWindow() {
if (editWindow) return editWindow;
// 编辑窗口(全屏置顶)
editWindow = document.createElement('div');
editWindow.id = 'edit-element-window';
editWindow.style.cssText = `
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: white;
z-index: 9999999;
overflow: auto;
display: none;
`;
// 编辑窗口功能栏
const editToolbar = document.createElement('div');
editToolbar.style.cssText = `
position: sticky;
top: 0;
background: #333;
padding: 12px 20px;
display: flex;
gap: 10px;
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
z-index: 10;
`;
// 功能按钮
removeElemBtn = document.createElement('button');
removeElemBtn.textContent = '移除元素';
removeElemBtn.style.padding = '8px 16px';
removeElemBtn.style.backgroundColor = '#ea4335';
removeElemBtn.style.color = 'white';
removeElemBtn.style.border = 'none';
removeElemBtn.style.borderRadius = '4px';
removeElemBtn.style.cursor = 'pointer';
// 移除模式提示
const removeHint = document.createElement('span');
removeHint.id = 'remove-mode-hint';
removeHint.textContent = '';
removeHint.style.color = 'white';
removeHint.style.marginLeft = '10px';
removeHint.style.alignSelf = 'center';
removeHint.style.fontSize = '14px';
saveEditBtn = document.createElement('button');
saveEditBtn.textContent = '保存编辑并截图';
saveEditBtn.style.padding = '8px 16px';
saveEditBtn.style.backgroundColor = '#34a853';
saveEditBtn.style.color = 'white';
saveEditBtn.style.border = 'none';
saveEditBtn.style.borderRadius = '4px';
saveEditBtn.style.cursor = 'pointer';
cancelEditBtn = document.createElement('button');
cancelEditBtn.textContent = '取消编辑';
cancelEditBtn.style.padding = '8px 16px';
cancelEditBtn.style.backgroundColor = '#999';
cancelEditBtn.style.color = 'white';
cancelEditBtn.style.border = 'none';
cancelEditBtn.style.borderRadius = '4px';
cancelEditBtn.style.cursor = 'pointer';
// 编辑内容容器
editContentContainer = document.createElement('div');
editContentContainer.id = 'edit-content-container';
editContentContainer.style.cssText = `
padding: 0;
margin: 0;
`;
// 创建编辑时的高亮层
editHighlight = document.createElement('div');
editHighlight.id = 'edit-element-highlight';
editHighlight.style.cssText = `
position: absolute;
background: rgba(234, 67, 53, 0.3);
border: 2px solid #ea4335;
pointer-events: none;
z-index: 99999999;
display: none;
`;
document.body.appendChild(editHighlight);
// 组装编辑窗口
editToolbar.appendChild(removeElemBtn);
editToolbar.appendChild(removeHint);
editToolbar.appendChild(saveEditBtn);
editToolbar.appendChild(cancelEditBtn);
editWindow.appendChild(editToolbar);
editWindow.appendChild(editContentContainer);
document.body.appendChild(editWindow);
// 绑定编辑窗口事件
bindEditEvents();
return editWindow;
}
// 绑定编辑窗口相关事件
function bindEditEvents() {
// 移除元素按钮事件
removeElemBtn.addEventListener('click', toggleRemoveMode);
// 保存编辑并截图
saveEditBtn.addEventListener('click', () => {
if (editedElementClone) {
captureAndSave(editedElementClone);
closeEditWindow();
}
});
// 取消编辑
cancelEditBtn.addEventListener('click', closeEditWindow);
// 绑定ESC退出移除模式
document.addEventListener('keydown', handleEditKeyDown);
}
// 切换移除元素模式
function toggleRemoveMode() {
isRemovingElem = !isRemovingElem;
const removeHint = document.getElementById('remove-mode-hint');
if (isRemovingElem) {
removeElemBtn.style.backgroundColor = '#ff6b6b';
removeHint.textContent = '移除模式:鼠标选择元素点击删除(ESC退出)';
// 绑定元素选择事件
editContentContainer.addEventListener('mousemove', handleEditMouseMove);
editContentContainer.addEventListener('click', handleEditElementClick);
} else {
removeElemBtn.style.backgroundColor = '#ea4335';
removeHint.textContent = '';
// 解绑事件并隐藏高亮
editContentContainer.removeEventListener('mousemove', handleEditMouseMove);
editContentContainer.removeEventListener('click', handleEditElementClick);
editHighlight.style.display = 'none';
}
}
// 编辑窗口键盘事件处理(ESC退出移除模式)
function handleEditKeyDown(e) {
if (!isEditing) return;
// ESC键退出移除模式
if (e.key === 'Escape') {
if (isRemovingElem) {
isRemovingElem = false;
const removeHint = document.getElementById('remove-mode-hint');
removeElemBtn.style.backgroundColor = '#ea4335';
removeHint.textContent = '';
editContentContainer.removeEventListener('mousemove', handleEditMouseMove);
editContentContainer.removeEventListener('click', handleEditElementClick);
editHighlight.style.display = 'none';
} else {
// 非移除模式下ESC关闭编辑窗口
closeEditWindow();
}
}
}
// 保存页面原始样式表(用于编辑时保留样式)
function saveOriginalStylesheets() {
originalStylesheets = [];
// 保存所有样式表
Array.from(document.styleSheets).forEach(stylesheet => {
try {
// 处理外部样式表
if (stylesheet.href) {
originalStylesheets.push(stylesheet.href);
} else {
// 处理内联样式表
const rules = Array.from(stylesheet.cssRules).map(rule => rule.cssText).join('\n');
originalStylesheets.push({ type: 'inline', content: rules });
}
} catch (e) {
console.log('无法访问样式表:', e);
}
});
}
// 在编辑窗口中恢复样式表
function restoreStylesInEditWindow() {
// 创建样式容器
const styleContainer = document.createElement('div');
styleContainer.id = 'original-styles-container';
// 恢复外部样式表
originalStylesheets.forEach(style => {
if (typeof style === 'string') {
// 外部样式表链接
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = style;
link.crossOrigin = 'anonymous';
styleContainer.appendChild(link);
} else if (style.type === 'inline') {
// 内联样式
const styleElem = document.createElement('style');
styleElem.textContent = style.content;
styleContainer.appendChild(styleElem);
}
});
// 添加到编辑窗口头部
if (editContentContainer.firstChild) {
editContentContainer.insertBefore(styleContainer, editContentContainer.firstChild);
} else {
editContentContainer.appendChild(styleContainer);
}
}
// 显示编辑窗口
function showEditWindow(targetElement) {
createEditWindow();
originalSelectedElement = targetElement;
// 保存原始样式表
saveOriginalStylesheets();
// 克隆元素(深拷贝保留DOM层级)
editedElementClone = targetElement.cloneNode(true);
// 保留原始尺寸和位置样式
const computedStyle = window.getComputedStyle(targetElement);
editedElementClone.style.width = computedStyle.width;
editedElementClone.style.minWidth = computedStyle.minWidth;
editedElementClone.style.maxWidth = computedStyle.maxWidth;
editedElementClone.style.margin = computedStyle.margin;
editedElementClone.style.padding = computedStyle.padding;
// 清空编辑内容容器并添加克隆元素
editContentContainer.innerHTML = '';
editContentContainer.appendChild(editedElementClone);
// 恢复样式表确保样式一致
restoreStylesInEditWindow();
// 显示窗口
editWindow.style.display = 'block';
isEditing = true;
}
// 关闭编辑窗口
function closeEditWindow() {
if (editWindow) {
editWindow.style.display = 'none';
}
isEditing = false;
isRemovingElem = false;
if (removeElemBtn) {
removeElemBtn.style.backgroundColor = '#ea4335';
}
if (editHighlight) {
editHighlight.style.display = 'none';
}
if (document.getElementById('remove-mode-hint')) {
document.getElementById('remove-mode-hint').textContent = '';
}
// 解绑编辑区事件
if (editContentContainer) {
editContentContainer.removeEventListener('mousemove', handleEditMouseMove);
editContentContainer.removeEventListener('click', handleEditElementClick);
}
}
// 编辑时鼠标移动高亮元素
function handleEditMouseMove(e) {
if (!isRemovingElem) return;
// 忽略工具栏元素
if (e.target.closest('#edit-element-window > div:first-child')) return;
const targetElem = e.target;
const rect = targetElem.getBoundingClientRect();
// 计算相对于视口的位置(编辑窗口是全屏的)
editHighlight.style.top = `${rect.top}px`;
editHighlight.style.left = `${rect.left}px`;
editHighlight.style.width = `${rect.width}px`;
editHighlight.style.height = `${rect.height}px`;
editHighlight.style.display = 'block';
}
// 编辑时点击移除元素
function handleEditElementClick(e) {
if (!isRemovingElem) return;
// 忽略工具栏元素
if (e.target.closest('#edit-element-window > div:first-child')) return;
const targetElem = e.target;
if (confirm('确定要移除这个元素吗?')) {
targetElem.remove();
editHighlight.style.display = 'none';
}
}
// 创建遮罩层
function createOverlay() {
if (document.getElementById('screenshot-overlay')) {
return document.getElementById('screenshot-overlay');
}
const overlay = document.createElement('div');
overlay.id = 'screenshot-overlay';
overlay.style.cssText = `
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
z-index: 999997;
display: none;
pointer-events: none;
`;
const hintContainer = document.createElement('div');
hintContainer.style.cssText = `
position: absolute;
top: 20px;
left: 50%;
transform: translateX(-50%);
pointer-events: auto;
`;
const hint = document.createElement('div');
hint.style.cssText = `
color: white;
font-size: 16px;
padding: 10px 20px;
background: rgba(0,0,0,0.5);
border-radius: 4px;
`;
hint.textContent = '[ 扩大选择 | ] 缩小选择 | 回车/点击确认 | ESC取消';
hintContainer.appendChild(hint);
overlay.appendChild(hintContainer);
document.body.appendChild(overlay);
return overlay;
}
// 显示/隐藏遮罩层
function toggleOverlay(show) {
const overlay = createOverlay();
overlay.style.display = show ? 'block' : 'none';
}
// 显示操作界面
function showUI() {
const ui = createUI();
ui.style.display = 'block';
bindEvents();
}
// 隐藏操作界面
function hideUI() {
if (uiContainer) {
uiContainer.style.display = 'none';
}
}
// 根据输入内容查找元素
function findElementByInput(inputVal) {
if (!inputVal.trim()) {
return null;
}
// 处理ID选择器(以#开头)
if (inputVal.startsWith('#')) {
const id = inputVal.slice(1);
return document.getElementById(id);
}
// 处理标签名
return document.querySelector(inputVal);
}
// 手动输入元素确认后的处理
function handleInputConfirm() {
const inputVal = elementInput.value.trim();
const status = document.getElementById('screenshot-status');
const info = document.getElementById('selected-element-info');
const captureBtn = document.getElementById('capture-button');
const editBtn = document.getElementById('edit-element-button');
const targetElement = findElementByInput(inputVal);
if (targetElement) {
selectedElement = targetElement;
// 显示元素信息和高亮
const elementInfo = targetElement.id ? `${targetElement.tagName.toLowerCase()}#${targetElement.id}` : targetElement.tagName.toLowerCase();
status.textContent = `已选中输入元素: <${elementInfo}>`;
status.style.color = '#333';
info.textContent = `已选择: <${elementInfo}>`;
info.style.color = '#34a853';
info.style.borderColor = '#34a853';
captureBtn.disabled = false;
editBtn.disabled = false;
// 显示高亮
updateHighlight(targetElement);
} else {
status.textContent = '未找到该元素,请检查输入格式';
status.style.color = '#ea4335';
info.textContent = '未选择任何元素';
info.style.color = '#666';
info.style.borderColor = '#ddd';
captureBtn.disabled = true;
editBtn.disabled = true;
selectedElement = null;
updateHighlight(null);
}
}
// 变量存储
let selectedElement = null;
let isSelecting = false;
let highlightOverlay = null;
let elementHistory = [];
let historyIndex = -1;
// 创建高亮覆盖层
function createHighlightOverlay() {
if (highlightOverlay) return highlightOverlay;
highlightOverlay = document.createElement('div');
highlightOverlay.style.cssText = `
position: absolute;
background: rgba(66, 133, 244, 0.3);
border: 2px solid #4285f4;
pointer-events: none;
z-index: 999998;
display: none;
transition: all 0.1s ease;
`;
document.body.appendChild(highlightOverlay);
return highlightOverlay;
}
// 更新高亮显示
function updateHighlight(element) {
if (!element) {
if (highlightOverlay) highlightOverlay.style.display = 'none';
return;
}
const rect = element.getBoundingClientRect();
const overlay = createHighlightOverlay();
overlay.style.top = `${rect.top + window.scrollY}px`;
overlay.style.left = `${rect.left + window.scrollX}px`;
overlay.style.width = `${rect.width}px`;
overlay.style.height = `${rect.height}px`;
overlay.style.display = 'block';
overlay.style.transform = 'scale(1)';
setTimeout(() => {
if (overlay) overlay.style.transform = 'scale(1.01)';
}, 50);
setTimeout(() => {
if (overlay) overlay.style.transform = 'scale(1)';
}, 100);
const status = document.getElementById('screenshot-status');
const elementInfo = element.id ? `${element.tagName.toLowerCase()}#${element.id}` : element.tagName.toLowerCase();
status.textContent = `已选择: <${elementInfo}>`;
}
// 过滤工具自身元素
function isToolElement(element) {
return element.id && (element.id.startsWith('element-screenshot-') || element.id.startsWith('screenshot-') || element.id.startsWith('edit-'));
}
// 获取元素的所有父级元素
function getParentElements(element) {
const parents = [];
let current = element.parentElement;
while (current) {
if (!isToolElement(current)) {
parents.push(current);
}
current = current.parentElement;
}
return parents;
}
// 获取元素的直接子级元素
function getChildElements(element) {
return Array.from(element.children).filter(child => !isToolElement(child));
}
// 向上选择父级元素
function selectParentElement() {
if (!selectedElement) return;
const parents = getParentElements(selectedElement);
if (parents.length > 0) {
if (historyIndex === elementHistory.length - 1) {
elementHistory.push(selectedElement);
}
historyIndex++;
selectedElement = parents[0];
updateHighlight(selectedElement);
}
}
// 向下选择子级元素
function selectChildElement() {
if (!selectedElement) return;
const children = getChildElements(selectedElement);
if (children.length > 0) {
if (historyIndex === elementHistory.length - 1) {
elementHistory.push(selectedElement);
}
historyIndex++;
selectedElement = children[0];
updateHighlight(selectedElement);
}
}
// 开始选择元素
function startSelecting() {
if (isSelecting) return;
isSelecting = true;
selectedElement = null;
elementHistory = [];
historyIndex = -1;
const status = document.getElementById('screenshot-status');
status.textContent = '移动鼠标选择初始元素(回车确认)...';
status.style.color = '#4285f4';
toggleOverlay(true);
document.body.style.cursor = 'crosshair';
document.getElementById('select-element-button').disabled = true;
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('click', handleMouseClick);
document.addEventListener('keydown', handleKeyDown);
}
// 结束选择元素
function stopSelecting(confirmed = false) {
isSelecting = false;
toggleOverlay(false);
document.body.style.cursor = '';
document.getElementById('select-element-button').disabled = false;
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('click', handleMouseClick);
document.removeEventListener('keydown', handleKeyDown);
if (highlightOverlay) highlightOverlay.style.display = 'none';
elementHistory = [];
historyIndex = -1;
const status = document.getElementById('screenshot-status');
const info = document.getElementById('selected-element-info');
const captureBtn = document.getElementById('capture-button');
const editBtn = document.getElementById('edit-element-button');
if (confirmed && selectedElement) {
status.textContent = '已选择元素,可编辑或直接截图';
status.style.color = '#333';
const elementInfo = selectedElement.id ? `${selectedElement.tagName.toLowerCase()}#${selectedElement.id}` : selectedElement.tagName.toLowerCase();
info.textContent = `已选择: <${elementInfo}>`;
info.style.color = '#34a853';
info.style.borderColor = '#34a853';
captureBtn.disabled = false;
editBtn.disabled = false;
} else {
status.textContent = '选择已取消';
status.style.color = '#ea4335';
info.textContent = '未选择任何元素';
info.style.color = '#666';
info.style.borderColor = '#ddd';
captureBtn.disabled = true;
editBtn.disabled = true;
selectedElement = null;
}
}
// 处理鼠标移动
function handleMouseMove(e) {
if (!isSelecting) return;
const elements = document.elementsFromPoint(e.clientX, e.clientY);
const targetElement = elements.find(el => !isToolElement(el));
if (targetElement) {
if (!selectedElement || targetElement !== selectedElement) {
selectedElement = targetElement;
elementHistory = [];
historyIndex = -1;
updateHighlight(targetElement);
}
} else {
updateHighlight(null);
selectedElement = null;
elementHistory = [];
historyIndex = -1;
}
}
// 处理鼠标点击
function handleMouseClick(e) {
if (!isSelecting) return;
e.stopPropagation();
e.preventDefault();
if (selectedElement) {
stopSelecting(true);
}
}
// 处理键盘事件
function handleKeyDown(e) {
if (!isSelecting) {
// 非选择状态下,支持输入框回车触发确认
if (document.activeElement === elementInput && e.key === 'Enter') {
e.preventDefault();
handleInputConfirm();
}
return;
}
// 选择状态下的键盘逻辑
if (e.key === 'Escape') {
stopSelecting(false);
return;
}
// 回车确认选择
if (e.key === 'Enter') {
e.preventDefault();
if (selectedElement) {
stopSelecting(true);
}
return;
}
if (e.key === '[') {
e.preventDefault();
selectParentElement();
return;
}
if (e.key === ']') {
e.preventDefault();
selectChildElement();
return;
}
}
// 捕获并保存截图
function captureAndSave(targetElem = null) {
const captureTarget = targetElem || selectedElement;
if (!captureTarget) return;
const status = document.getElementById('screenshot-status');
status.textContent = '正在生成截图...';
status.style.color = '#fbbc05';
html2canvas(captureTarget, {
scale: window.devicePixelRatio || 1,
useCORS: true,
logging: false,
allowTaint: false,
// 确保截图包含所有样式
backgroundColor: null
}).then(canvas => {
const elementName = captureTarget.tagName.toLowerCase();
const fileName = targetElem ? `${elementName}-edited-screenshot-${new Date().getTime()}.png` : `${elementName}-screenshot-${new Date().getTime()}.png`;
const link = document.createElement('a');
link.download = fileName;
link.href = canvas.toDataURL('image/png');
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
status.textContent = '截图已保存!';
status.style.color = '#34a853';
}).catch(error => {
console.error('截图失败:', error);
status.textContent = '截图失败,请重试';
status.style.color = '#ea4335';
});
}
// 绑定事件
function bindEvents() {
if (closeButton) {
closeButton.removeEventListener('click', handleClose);
}
if (inputConfirmBtn) {
inputConfirmBtn.removeEventListener('click', handleInputConfirm);
}
const selectBtn = document.getElementById('select-element-button');
const captureBtn = document.getElementById('capture-button');
const editBtn = document.getElementById('edit-element-button');
// 鼠标选择元素按钮
if (selectBtn) {
selectBtn.removeEventListener('click', startSelecting);
selectBtn.addEventListener('click', startSelecting);
}
// 保存截图按钮
if (captureBtn) {
captureBtn.removeEventListener('click', () => captureAndSave());
captureBtn.addEventListener('click', () => captureAndSave());
}
// 编辑元素按钮
if (editBtn) {
editBtn.removeEventListener('click', () => {
if (selectedElement) {
showEditWindow(selectedElement);
}
});
editBtn.addEventListener('click', () => {
if (selectedElement) {
showEditWindow(selectedElement);
}
});
}
// 关闭按钮
if (closeButton) {
closeButton.addEventListener('click', handleClose);
}
// 手动输入确认按钮
if (inputConfirmBtn) {
inputConfirmBtn.addEventListener('click', handleInputConfirm);
}
// 输入框回车事件
elementInput.removeEventListener('keydown', inputEnterHandler);
elementInput.addEventListener('keydown', inputEnterHandler);
}
// 输入框回车辅助处理函数
function inputEnterHandler(e) {
if (e.key === 'Enter') {
e.preventDefault();
handleInputConfirm();
}
}
// 关闭按钮处理函数
function handleClose() {
if (isSelecting) {
stopSelecting(false);
}
if (isEditing) {
closeEditWindow();
}
hideUI();
}
// 注册油猴菜单命令
GM_registerMenuCommand('点击截图', showUI);
// 初始化界面(默认隐藏)
createUI();
hideUI();
})();