添加区域模式,优化提示
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"allow": [
|
"allow": [
|
||||||
"Bash(wc:*)"
|
"Bash(wc:*)",
|
||||||
|
"Bash(cat:*)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
138
content.css
138
content.css
@@ -10,59 +10,30 @@
|
|||||||
position: relative !important;
|
position: relative !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 元素模式下的悬停效果 */
|
/* 元素模式下的悬停效果 - 移除伪元素方案,改用 JS 动态创建 */
|
||||||
body.blurtext-mode .blurtext-blurred:hover::after {
|
/* body.blurtext-mode .blurtext-blurred:hover::after 已移除 */
|
||||||
content: '点击取消模糊' !important;
|
|
||||||
position: absolute !important;
|
/* 元素模式悬停提示工具栏(JS 动态创建) */
|
||||||
top: 50% !important;
|
.blurtext-element-tooltip {
|
||||||
left: 50% !important;
|
position: fixed !important;
|
||||||
transform: translate(-50%, -50%) !important;
|
|
||||||
background: rgba(102, 126, 234, 0.95) !important;
|
background: rgba(102, 126, 234, 0.95) !important;
|
||||||
color: white !important;
|
color: white !important;
|
||||||
padding: 4px 8px !important;
|
|
||||||
border-radius: 4px !important;
|
|
||||||
font-size: 12px !important;
|
|
||||||
white-space: nowrap !important;
|
|
||||||
z-index: 999999 !important;
|
|
||||||
pointer-events: none !important;
|
|
||||||
filter: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 文本选择模式包裹的元素悬停效果 */
|
|
||||||
.blurtext-selection-wrapped {
|
|
||||||
transition: all 0.1s ease !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.blurtext-selection-wrapped:hover {
|
|
||||||
background-color: rgba(102, 126, 234, 0.2) !important;
|
|
||||||
outline: 2px solid rgba(102, 126, 234, 0.5) !important;
|
|
||||||
outline-offset: 2px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.blurtext-selection-wrapped:hover::after {
|
|
||||||
content: '🔓 点击恢复' !important;
|
|
||||||
position: absolute !important;
|
|
||||||
top: 50% !important;
|
|
||||||
left: 50% !important;
|
|
||||||
transform: translate(-50%, -50%) !important;
|
|
||||||
background: rgba(102, 126, 234, 0.98) !important;
|
|
||||||
color: white !important;
|
|
||||||
padding: 6px 12px !important;
|
padding: 6px 12px !important;
|
||||||
border-radius: 6px !important;
|
border-radius: 6px !important;
|
||||||
font-size: 13px !important;
|
font-size: 13px !important;
|
||||||
font-weight: 600 !important;
|
font-weight: 600 !important;
|
||||||
white-space: nowrap !important;
|
white-space: nowrap !important;
|
||||||
z-index: 999999 !important;
|
z-index: 2147483647 !important;
|
||||||
pointer-events: none !important;
|
pointer-events: none !important;
|
||||||
filter: none !important;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3) !important;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3) !important;
|
||||||
animation: blurtext-tooltipPop 0.15s ease !important;
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
|
||||||
|
animation: blurtext-tooltipFadeIn 0.15s ease !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes blurtext-tooltipPop {
|
@keyframes blurtext-tooltipFadeIn {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translate(-50%, -50%) scale(0.8);
|
transform: translate(-50%, -50%) scale(0.9);
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
@@ -70,6 +41,42 @@ body.blurtext-mode .blurtext-blurred:hover::after {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 文本选择模式包裹的元素悬停效果 */
|
||||||
|
.blurtext-selection-wrapped {
|
||||||
|
display: inline !important;
|
||||||
|
position: relative !important;
|
||||||
|
cursor: pointer !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 移除伪元素提示,改用 JS 动态创建(避免被模糊效果影响) */
|
||||||
|
|
||||||
|
/* 文本选择错误提示(显示在选区下方) */
|
||||||
|
.blurtext-selection-error {
|
||||||
|
background: #f44336 !important;
|
||||||
|
color: white !important;
|
||||||
|
padding: 8px 16px !important;
|
||||||
|
border-radius: 6px !important;
|
||||||
|
font-size: 13px !important;
|
||||||
|
font-weight: 500 !important;
|
||||||
|
box-shadow: 0 2px 8px rgba(244, 67, 54, 0.4) !important;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
|
||||||
|
animation: blurtext-errorPop 0.2s ease !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
white-space: nowrap !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes blurtext-errorPop {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(-50%) translateY(-5px) scale(0.9);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(-50%) translateY(0) scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 模糊模式下的鼠标样式 */
|
/* 模糊模式下的鼠标样式 */
|
||||||
body.blurtext-mode * {
|
body.blurtext-mode * {
|
||||||
cursor: crosshair !important;
|
cursor: crosshair !important;
|
||||||
@@ -149,7 +156,52 @@ body.blurtext-mode * {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 文本选择模式包裹的元素 */
|
/* ========== 区域模式样式 ========== */
|
||||||
.blurtext-selection-wrapped {
|
|
||||||
display: inline !important;
|
/* 绘制框(拖动时显示) */
|
||||||
|
.blurtext-drawing-box {
|
||||||
|
border: 2px dashed #667eea !important;
|
||||||
|
background: rgba(102, 126, 234, 0.1) !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.5) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 区域覆盖层 */
|
||||||
|
.blurtext-area-overlay {
|
||||||
|
background: rgba(255, 255, 255, 0.1) !important;
|
||||||
|
backdrop-filter: blur(var(--blur-intensity, 10px)) !important;
|
||||||
|
-webkit-backdrop-filter: blur(var(--blur-intensity, 10px)) !important;
|
||||||
|
border: none !important;
|
||||||
|
box-sizing: border-box !important;
|
||||||
|
transition: all 0.2s ease !important;
|
||||||
|
user-select: none !important;
|
||||||
|
cursor: pointer !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blurtext-area-overlay:hover {
|
||||||
|
outline: 2px solid rgba(102, 126, 234, 0.5) !important;
|
||||||
|
outline-offset: -2px !important;
|
||||||
|
background: rgba(255, 255, 255, 0.15) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 区域覆盖层悬停提示 */
|
||||||
|
.blurtext-area-overlay:hover::after {
|
||||||
|
content: '点击恢复此区域' !important;
|
||||||
|
position: absolute !important;
|
||||||
|
top: 50% !important;
|
||||||
|
left: 50% !important;
|
||||||
|
transform: translate(-50%, -50%) !important;
|
||||||
|
background: rgba(102, 126, 234, 0.95) !important;
|
||||||
|
color: white !important;
|
||||||
|
padding: 6px 12px !important;
|
||||||
|
border-radius: 6px !important;
|
||||||
|
font-size: 13px !important;
|
||||||
|
font-weight: 600 !important;
|
||||||
|
white-space: nowrap !important;
|
||||||
|
z-index: 999999 !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
backdrop-filter: none !important;
|
||||||
|
-webkit-backdrop-filter: none !important;
|
||||||
|
filter: none !important;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3) !important;
|
||||||
}
|
}
|
||||||
|
|||||||
335
content.js
335
content.js
@@ -5,11 +5,19 @@
|
|||||||
console.log('[BlurText] Content script loaded');
|
console.log('[BlurText] Content script loaded');
|
||||||
|
|
||||||
let isBlurMode = false;
|
let isBlurMode = false;
|
||||||
let blurMode = 'element'; // 'element' or 'selection'
|
let blurMode = 'element'; // 'element', 'selection', or 'area'
|
||||||
let blurIntensity = 10;
|
let blurIntensity = 10;
|
||||||
let blurredElements = new Set();
|
let blurredElements = new Set();
|
||||||
let hintElement = null;
|
let hintElement = null;
|
||||||
let blurButton = null; // 浮动模糊按钮
|
let blurButton = null; // 浮动模糊按钮
|
||||||
|
let elementTooltip = null; // 元素模式悬停提示
|
||||||
|
|
||||||
|
// 区域模式相关变量
|
||||||
|
let isDrawing = false;
|
||||||
|
let startX = 0;
|
||||||
|
let startY = 0;
|
||||||
|
let drawingBox = null;
|
||||||
|
let areaOverlays = []; // 存储所有区域覆盖层
|
||||||
|
|
||||||
// 初始化:从存储中加载配置
|
// 初始化:从存储中加载配置
|
||||||
chrome.storage.local.get(['blurIntensity'], (result) => {
|
chrome.storage.local.get(['blurIntensity'], (result) => {
|
||||||
@@ -53,7 +61,12 @@
|
|||||||
function enableBlurMode() {
|
function enableBlurMode() {
|
||||||
console.log('[BlurText] Enabling blur mode, mode:', blurMode);
|
console.log('[BlurText] Enabling blur mode, mode:', blurMode);
|
||||||
|
|
||||||
const modeText = blurMode === 'selection' ? '文本选择模式 - 拖动选择文字后点击模糊按钮' : '元素模式 - 点击元素进行模糊';
|
let modeText = '元素模式 - 点击元素进行模糊';
|
||||||
|
if (blurMode === 'selection') {
|
||||||
|
modeText = '文本选择模式 - 拖动选择文字后点击模糊按钮';
|
||||||
|
} else if (blurMode === 'area') {
|
||||||
|
modeText = '区域模式 - 拖动鼠标绘制模糊区域';
|
||||||
|
}
|
||||||
showHint(`模糊模式已开启 - ${modeText},按 ESC 退出`);
|
showHint(`模糊模式已开启 - ${modeText},按 ESC 退出`);
|
||||||
|
|
||||||
// 根据模式添加对应的样式和事件
|
// 根据模式添加对应的样式和事件
|
||||||
@@ -65,9 +78,15 @@
|
|||||||
} else if (blurMode === 'selection') {
|
} else if (blurMode === 'selection') {
|
||||||
// 文本选择模式不需要 crosshair 光标
|
// 文本选择模式不需要 crosshair 光标
|
||||||
document.addEventListener('mouseup', handleTextSelection, true);
|
document.addEventListener('mouseup', handleTextSelection, true);
|
||||||
|
} else if (blurMode === 'area') {
|
||||||
|
// 区域模式:使用 crosshair 光标并添加绘制事件
|
||||||
|
document.body.classList.add('blurtext-mode');
|
||||||
|
document.addEventListener('mousedown', handleAreaMouseDown, true);
|
||||||
|
document.addEventListener('mousemove', handleAreaMouseMove, true);
|
||||||
|
document.addEventListener('mouseup', handleAreaMouseUp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 键盘事件对两种模式都需要
|
// 键盘事件对所有模式都需要
|
||||||
document.addEventListener('keydown', handleKeydown, true);
|
document.addEventListener('keydown', handleKeydown, true);
|
||||||
|
|
||||||
console.log('[BlurText] Event listeners attached');
|
console.log('[BlurText] Event listeners attached');
|
||||||
@@ -78,6 +97,8 @@
|
|||||||
document.body.classList.remove('blurtext-mode');
|
document.body.classList.remove('blurtext-mode');
|
||||||
hideHint();
|
hideHint();
|
||||||
hideBlurButton();
|
hideBlurButton();
|
||||||
|
hideDrawingBox();
|
||||||
|
hideElementTooltip();
|
||||||
|
|
||||||
// 移除所有事件监听
|
// 移除所有事件监听
|
||||||
document.removeEventListener('click', handleClick, true);
|
document.removeEventListener('click', handleClick, true);
|
||||||
@@ -85,6 +106,9 @@
|
|||||||
document.removeEventListener('mouseover', handleMouseOver, true);
|
document.removeEventListener('mouseover', handleMouseOver, true);
|
||||||
document.removeEventListener('mouseout', handleMouseOut, true);
|
document.removeEventListener('mouseout', handleMouseOut, true);
|
||||||
document.removeEventListener('mouseup', handleTextSelection, true);
|
document.removeEventListener('mouseup', handleTextSelection, true);
|
||||||
|
document.removeEventListener('mousedown', handleAreaMouseDown, true);
|
||||||
|
document.removeEventListener('mousemove', handleAreaMouseMove, true);
|
||||||
|
document.removeEventListener('mouseup', handleAreaMouseUp, true);
|
||||||
|
|
||||||
// 清除所有高亮和预览
|
// 清除所有高亮和预览
|
||||||
removeAllHighlights();
|
removeAllHighlights();
|
||||||
@@ -102,10 +126,15 @@
|
|||||||
document.removeEventListener('mouseover', handleMouseOver, true);
|
document.removeEventListener('mouseover', handleMouseOver, true);
|
||||||
document.removeEventListener('mouseout', handleMouseOut, true);
|
document.removeEventListener('mouseout', handleMouseOut, true);
|
||||||
document.removeEventListener('mouseup', handleTextSelection, true);
|
document.removeEventListener('mouseup', handleTextSelection, true);
|
||||||
|
document.removeEventListener('mousedown', handleAreaMouseDown, true);
|
||||||
|
document.removeEventListener('mousemove', handleAreaMouseMove, true);
|
||||||
|
document.removeEventListener('mouseup', handleAreaMouseUp, true);
|
||||||
|
|
||||||
// 清除旧模式的UI元素
|
// 清除旧模式的UI元素
|
||||||
hideBlurButton();
|
hideBlurButton();
|
||||||
removeAllHighlights();
|
removeAllHighlights();
|
||||||
|
hideDrawingBox();
|
||||||
|
hideElementTooltip();
|
||||||
|
|
||||||
// 根据新模式添加事件监听和样式
|
// 根据新模式添加事件监听和样式
|
||||||
if (blurMode === 'element') {
|
if (blurMode === 'element') {
|
||||||
@@ -118,6 +147,13 @@
|
|||||||
// 文本选择模式不需要 crosshair 光标
|
// 文本选择模式不需要 crosshair 光标
|
||||||
document.addEventListener('mouseup', handleTextSelection, true);
|
document.addEventListener('mouseup', handleTextSelection, true);
|
||||||
showHint('已切换到文本选择模式 - 拖动选择文字后点击模糊按钮', 3000);
|
showHint('已切换到文本选择模式 - 拖动选择文字后点击模糊按钮', 3000);
|
||||||
|
} else if (blurMode === 'area') {
|
||||||
|
// 区域模式
|
||||||
|
document.body.classList.add('blurtext-mode');
|
||||||
|
document.addEventListener('mousedown', handleAreaMouseDown, true);
|
||||||
|
document.addEventListener('mousemove', handleAreaMouseMove, true);
|
||||||
|
document.addEventListener('mouseup', handleAreaMouseUp, true);
|
||||||
|
showHint('已切换到区域模式 - 拖动鼠标绘制模糊区域', 3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[BlurText] Mode switched successfully');
|
console.log('[BlurText] Mode switched successfully');
|
||||||
@@ -222,6 +258,33 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 显示元素悬停提示
|
||||||
|
function showElementTooltip(element, text) {
|
||||||
|
// 移除旧提示
|
||||||
|
hideElementTooltip();
|
||||||
|
|
||||||
|
// 获取元素位置
|
||||||
|
const rect = element.getBoundingClientRect();
|
||||||
|
|
||||||
|
// 创建提示元素
|
||||||
|
elementTooltip = document.createElement('div');
|
||||||
|
elementTooltip.className = 'blurtext-element-tooltip';
|
||||||
|
elementTooltip.textContent = text;
|
||||||
|
elementTooltip.style.left = `${rect.left + rect.width / 2}px`;
|
||||||
|
elementTooltip.style.top = `${rect.top + rect.height / 2}px`;
|
||||||
|
elementTooltip.style.transform = 'translate(-50%, -50%)';
|
||||||
|
|
||||||
|
document.body.appendChild(elementTooltip);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 隐藏元素悬停提示
|
||||||
|
function hideElementTooltip() {
|
||||||
|
if (elementTooltip && elementTooltip.parentNode) {
|
||||||
|
elementTooltip.parentNode.removeChild(elementTooltip);
|
||||||
|
elementTooltip = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 模糊选中的文本
|
// 模糊选中的文本
|
||||||
function blurSelectedText() {
|
function blurSelectedText() {
|
||||||
const selection = window.getSelection();
|
const selection = window.getSelection();
|
||||||
@@ -230,21 +293,76 @@
|
|||||||
try {
|
try {
|
||||||
const range = selection.getRangeAt(0);
|
const range = selection.getRangeAt(0);
|
||||||
|
|
||||||
|
// 获取选中的文本内容
|
||||||
|
const selectedText = range.toString();
|
||||||
|
|
||||||
|
// 验证选区是否符合要求
|
||||||
|
if (!selectedText.trim()) {
|
||||||
|
console.log('[BlurText] No text selected');
|
||||||
|
hideBlurButton();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 限制:不允许包含换行
|
||||||
|
if (selectedText.includes('\n') || selectedText.includes('\r')) {
|
||||||
|
console.log('[BlurText] Selection contains line breaks');
|
||||||
|
showSelectionError(selection, '不支持跨行选择');
|
||||||
|
hideBlurButton();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 限制:不允许包含多个空格(允许单个空格)
|
||||||
|
if (/\s{2,}/.test(selectedText)) {
|
||||||
|
console.log('[BlurText] Selection contains multiple spaces');
|
||||||
|
showSelectionError(selection, '不支持多个连续空格');
|
||||||
|
hideBlurButton();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 限制:检查是否跨越多个元素
|
||||||
|
const startContainer = range.startContainer;
|
||||||
|
const endContainer = range.endContainer;
|
||||||
|
|
||||||
|
// 如果起始和结束容器不同,则跨越了多个节点
|
||||||
|
if (startContainer !== endContainer) {
|
||||||
|
console.log('[BlurText] Selection spans multiple elements');
|
||||||
|
showSelectionError(selection, '不支持跨元素选择');
|
||||||
|
hideBlurButton();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 限制:只能选择文本节点
|
||||||
|
if (startContainer.nodeType !== Node.TEXT_NODE) {
|
||||||
|
console.log('[BlurText] Selection is not in a text node');
|
||||||
|
showSelectionError(selection, '请选择纯文本内容');
|
||||||
|
hideBlurButton();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 创建 span 包裹选中的文本
|
// 创建 span 包裹选中的文本
|
||||||
const span = document.createElement('span');
|
const span = document.createElement('span');
|
||||||
span.className = 'blurtext-blurred blurtext-selection-wrapped';
|
span.className = 'blurtext-blurred blurtext-selection-wrapped';
|
||||||
span.style.setProperty('--blur-intensity', `${blurIntensity}px`);
|
span.style.setProperty('--blur-intensity', `${blurIntensity}px`);
|
||||||
span.style.cursor = 'pointer';
|
span.style.cursor = 'pointer';
|
||||||
span.title = '点击恢复此段文本';
|
|
||||||
|
// 添加鼠标悬停事件,显示恢复提示
|
||||||
|
span.addEventListener('mouseenter', () => {
|
||||||
|
showElementTooltip(span, '点击恢复此文本');
|
||||||
|
});
|
||||||
|
|
||||||
|
span.addEventListener('mouseleave', () => {
|
||||||
|
hideElementTooltip();
|
||||||
|
});
|
||||||
|
|
||||||
// 添加点击事件,允许单独恢复
|
// 添加点击事件,允许单独恢复
|
||||||
span.addEventListener('click', (e) => {
|
span.addEventListener('click', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
hideElementTooltip(); // 点击后立即隐藏提示
|
||||||
unblurSelectionSpan(span);
|
unblurSelectionSpan(span);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 包裹选中的内容
|
// 使用 surroundContents(在严格限制下应该不会失败)
|
||||||
range.surroundContents(span);
|
range.surroundContents(span);
|
||||||
|
|
||||||
// 添加到模糊元素集合
|
// 添加到模糊元素集合
|
||||||
@@ -257,16 +375,43 @@
|
|||||||
|
|
||||||
// 隐藏按钮
|
// 隐藏按钮
|
||||||
hideBlurButton();
|
hideBlurButton();
|
||||||
|
|
||||||
// 显示提示
|
|
||||||
showHint('文本已模糊(点击可单独恢复)', 2000);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[BlurText] Error blurring selection:', error);
|
console.error('[BlurText] Error blurring selection:', error);
|
||||||
showHint('无法模糊该选区(可能包含复杂的HTML结构)', 3000);
|
showSelectionError(selection, '无法模糊该选区');
|
||||||
hideBlurButton();
|
hideBlurButton();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 在选区位置显示错误提示
|
||||||
|
function showSelectionError(selection, message) {
|
||||||
|
if (!selection.rangeCount) return;
|
||||||
|
|
||||||
|
const range = selection.getRangeAt(0);
|
||||||
|
const rect = range.getBoundingClientRect();
|
||||||
|
|
||||||
|
// 创建错误提示元素
|
||||||
|
const errorTooltip = document.createElement('div');
|
||||||
|
errorTooltip.className = 'blurtext-selection-error';
|
||||||
|
errorTooltip.textContent = message;
|
||||||
|
errorTooltip.style.position = 'fixed';
|
||||||
|
errorTooltip.style.left = `${rect.left + rect.width / 2}px`;
|
||||||
|
errorTooltip.style.top = `${rect.bottom + 10}px`;
|
||||||
|
errorTooltip.style.transform = 'translateX(-50%)';
|
||||||
|
errorTooltip.style.zIndex = '2147483647';
|
||||||
|
|
||||||
|
document.body.appendChild(errorTooltip);
|
||||||
|
|
||||||
|
// 清除选择
|
||||||
|
selection.removeAllRanges();
|
||||||
|
|
||||||
|
// 2秒后自动移除
|
||||||
|
setTimeout(() => {
|
||||||
|
if (errorTooltip.parentNode) {
|
||||||
|
errorTooltip.parentNode.removeChild(errorTooltip);
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
// 恢复单个选择模式的模糊段落
|
// 恢复单个选择模式的模糊段落
|
||||||
function unblurSelectionSpan(span) {
|
function unblurSelectionSpan(span) {
|
||||||
if (!span || !span.parentNode) return;
|
if (!span || !span.parentNode) return;
|
||||||
@@ -276,7 +421,7 @@
|
|||||||
// 从集合中移除
|
// 从集合中移除
|
||||||
blurredElements.delete(span);
|
blurredElements.delete(span);
|
||||||
|
|
||||||
// 获取 span 的内容
|
// 获取 span 的内容(保持子节点结构)
|
||||||
const fragment = document.createDocumentFragment();
|
const fragment = document.createDocumentFragment();
|
||||||
while (span.firstChild) {
|
while (span.firstChild) {
|
||||||
fragment.appendChild(span.firstChild);
|
fragment.appendChild(span.firstChild);
|
||||||
@@ -285,9 +430,6 @@
|
|||||||
// 用原内容替换 span
|
// 用原内容替换 span
|
||||||
span.parentNode.replaceChild(fragment, span);
|
span.parentNode.replaceChild(fragment, span);
|
||||||
|
|
||||||
// 显示提示
|
|
||||||
showHint('已恢复此段文本', 1500);
|
|
||||||
|
|
||||||
console.log('[BlurText] Selection span removed, remaining elements:', blurredElements.size);
|
console.log('[BlurText] Selection span removed, remaining elements:', blurredElements.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,13 +438,20 @@
|
|||||||
if (!isBlurMode || blurMode !== 'element') return;
|
if (!isBlurMode || blurMode !== 'element') return;
|
||||||
|
|
||||||
const target = e.target;
|
const target = e.target;
|
||||||
if (target.classList.contains('blurtext-hint') ||
|
if (target.classList.contains('blurtext-hint')) {
|
||||||
target.classList.contains('blurtext-blurred')) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 移除之前的高亮
|
// 如果是已模糊的元素,显示恢复提示(不添加高亮)
|
||||||
|
if (target.classList.contains('blurtext-blurred')) {
|
||||||
|
removeAllHighlights(); // 移除其他高亮
|
||||||
|
showElementTooltip(target, '点击取消模糊');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除之前的高亮和提示
|
||||||
removeAllHighlights();
|
removeAllHighlights();
|
||||||
|
hideElementTooltip();
|
||||||
|
|
||||||
// 直接高亮元素
|
// 直接高亮元素
|
||||||
target.classList.add('blurtext-highlight');
|
target.classList.add('blurtext-highlight');
|
||||||
@@ -320,6 +469,9 @@
|
|||||||
function handleMouseOut(e) {
|
function handleMouseOut(e) {
|
||||||
if (!isBlurMode || blurMode !== 'element') return;
|
if (!isBlurMode || blurMode !== 'element') return;
|
||||||
|
|
||||||
|
// 隐藏提示
|
||||||
|
hideElementTooltip();
|
||||||
|
|
||||||
// 延迟移除,避免在元素间移动时闪烁
|
// 延迟移除,避免在元素间移动时闪烁
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// 检查鼠标是否还在模糊模式下的元素上
|
// 检查鼠标是否还在模糊模式下的元素上
|
||||||
@@ -346,6 +498,9 @@
|
|||||||
element.classList.remove('blurtext-blurred');
|
element.classList.remove('blurtext-blurred');
|
||||||
element.style.removeProperty('--blur-intensity');
|
element.style.removeProperty('--blur-intensity');
|
||||||
blurredElements.delete(element);
|
blurredElements.delete(element);
|
||||||
|
|
||||||
|
// 隐藏提示气泡(因为元素已不再模糊)
|
||||||
|
hideElementTooltip();
|
||||||
} else {
|
} else {
|
||||||
// 添加模糊
|
// 添加模糊
|
||||||
console.log('[BlurText] Adding blur to element, intensity:', blurIntensity);
|
console.log('[BlurText] Adding blur to element, intensity:', blurIntensity);
|
||||||
@@ -364,12 +519,160 @@
|
|||||||
});
|
});
|
||||||
blurredElements.clear();
|
blurredElements.clear();
|
||||||
|
|
||||||
|
// 清除所有区域覆盖层
|
||||||
|
areaOverlays.forEach(overlay => {
|
||||||
|
if (overlay.parentNode) {
|
||||||
|
overlay.parentNode.removeChild(overlay);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
areaOverlays = [];
|
||||||
|
|
||||||
// 如果在模糊模式下,显示提示
|
// 如果在模糊模式下,显示提示
|
||||||
if (isBlurMode) {
|
if (isBlurMode) {
|
||||||
showHint('已清除所有模糊效果', 2000);
|
showHint('已清除所有模糊效果', 2000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========== 区域模式相关函数 ==========
|
||||||
|
|
||||||
|
// 处理区域模式鼠标按下
|
||||||
|
function handleAreaMouseDown(e) {
|
||||||
|
if (!isBlurMode || blurMode !== 'area') return;
|
||||||
|
|
||||||
|
// 忽略提示元素和已有的区域覆盖层
|
||||||
|
if (e.target.classList.contains('blurtext-hint') ||
|
||||||
|
e.target.classList.contains('blurtext-area-overlay') ||
|
||||||
|
e.target.classList.contains('blurtext-area-close')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否点击了关闭按钮
|
||||||
|
if (e.target.classList.contains('blurtext-area-close')) {
|
||||||
|
const overlay = e.target.parentElement;
|
||||||
|
removeAreaOverlay(overlay);
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isDrawing = true;
|
||||||
|
startX = e.pageX;
|
||||||
|
startY = e.pageY;
|
||||||
|
|
||||||
|
// 创建绘制框
|
||||||
|
drawingBox = document.createElement('div');
|
||||||
|
drawingBox.className = 'blurtext-drawing-box';
|
||||||
|
drawingBox.style.position = 'absolute';
|
||||||
|
drawingBox.style.left = startX + 'px';
|
||||||
|
drawingBox.style.top = startY + 'px';
|
||||||
|
drawingBox.style.width = '0px';
|
||||||
|
drawingBox.style.height = '0px';
|
||||||
|
drawingBox.style.zIndex = '2147483646';
|
||||||
|
document.body.appendChild(drawingBox);
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理区域模式鼠标移动
|
||||||
|
function handleAreaMouseMove(e) {
|
||||||
|
if (!isBlurMode || blurMode !== 'area' || !isDrawing || !drawingBox) return;
|
||||||
|
|
||||||
|
const currentX = e.pageX;
|
||||||
|
const currentY = e.pageY;
|
||||||
|
|
||||||
|
const width = Math.abs(currentX - startX);
|
||||||
|
const height = Math.abs(currentY - startY);
|
||||||
|
const left = Math.min(currentX, startX);
|
||||||
|
const top = Math.min(currentY, startY);
|
||||||
|
|
||||||
|
drawingBox.style.left = left + 'px';
|
||||||
|
drawingBox.style.top = top + 'px';
|
||||||
|
drawingBox.style.width = width + 'px';
|
||||||
|
drawingBox.style.height = height + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理区域模式鼠标释放
|
||||||
|
function handleAreaMouseUp(e) {
|
||||||
|
if (!isBlurMode || blurMode !== 'area' || !isDrawing || !drawingBox) return;
|
||||||
|
|
||||||
|
isDrawing = false;
|
||||||
|
|
||||||
|
const width = parseInt(drawingBox.style.width);
|
||||||
|
const height = parseInt(drawingBox.style.height);
|
||||||
|
|
||||||
|
// 只有当区域足够大时才创建模糊覆盖层(至少 20x20 像素)
|
||||||
|
if (width > 20 && height > 20) {
|
||||||
|
createAreaOverlay(
|
||||||
|
parseInt(drawingBox.style.left),
|
||||||
|
parseInt(drawingBox.style.top),
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除绘制框
|
||||||
|
if (drawingBox.parentNode) {
|
||||||
|
drawingBox.parentNode.removeChild(drawingBox);
|
||||||
|
}
|
||||||
|
drawingBox = null;
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建区域覆盖层
|
||||||
|
function createAreaOverlay(left, top, width, height) {
|
||||||
|
const overlay = document.createElement('div');
|
||||||
|
overlay.className = 'blurtext-area-overlay';
|
||||||
|
overlay.style.position = 'absolute';
|
||||||
|
overlay.style.left = left + 'px';
|
||||||
|
overlay.style.top = top + 'px';
|
||||||
|
overlay.style.width = width + 'px';
|
||||||
|
overlay.style.height = height + 'px';
|
||||||
|
overlay.style.setProperty('--blur-intensity', `${blurIntensity}px`);
|
||||||
|
overlay.style.zIndex = '2147483645';
|
||||||
|
|
||||||
|
// 点击覆盖层恢复区域
|
||||||
|
overlay.addEventListener('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
removeAreaOverlay(overlay);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
areaOverlays.push(overlay);
|
||||||
|
|
||||||
|
// 添加到模糊元素集合(用于统一管理强度)
|
||||||
|
blurredElements.add(overlay);
|
||||||
|
|
||||||
|
console.log('[BlurText] Area overlay created, total overlays:', areaOverlays.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除区域覆盖层
|
||||||
|
function removeAreaOverlay(overlay) {
|
||||||
|
const index = areaOverlays.indexOf(overlay);
|
||||||
|
if (index > -1) {
|
||||||
|
areaOverlays.splice(index, 1);
|
||||||
|
}
|
||||||
|
blurredElements.delete(overlay);
|
||||||
|
if (overlay.parentNode) {
|
||||||
|
overlay.parentNode.removeChild(overlay);
|
||||||
|
}
|
||||||
|
console.log('[BlurText] Area overlay removed, remaining:', areaOverlays.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 隐藏绘制框
|
||||||
|
function hideDrawingBox() {
|
||||||
|
if (drawingBox && drawingBox.parentNode) {
|
||||||
|
drawingBox.parentNode.removeChild(drawingBox);
|
||||||
|
drawingBox = null;
|
||||||
|
}
|
||||||
|
isDrawing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 区域模式函数结束 ==========
|
||||||
|
|
||||||
// 更新所有已模糊元素的强度
|
// 更新所有已模糊元素的强度
|
||||||
function updateAllBlurIntensity() {
|
function updateAllBlurIntensity() {
|
||||||
blurredElements.forEach(element => {
|
blurredElements.forEach(element => {
|
||||||
|
|||||||
@@ -168,7 +168,7 @@
|
|||||||
|
|
||||||
.mode-buttons {
|
.mode-buttons {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,6 +243,10 @@
|
|||||||
<span class="mode-icon">📝</span>
|
<span class="mode-icon">📝</span>
|
||||||
<span class="mode-label">文本选择</span>
|
<span class="mode-label">文本选择</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button class="mode-btn" id="modeArea" data-mode="area">
|
||||||
|
<span class="mode-icon">🔲</span>
|
||||||
|
<span class="mode-label">区域模式</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
13
popup.js
13
popup.js
@@ -13,6 +13,7 @@ const intensityValue = document.getElementById('intensityValue');
|
|||||||
const statusDiv = document.getElementById('status');
|
const statusDiv = document.getElementById('status');
|
||||||
const modeElementBtn = document.getElementById('modeElement');
|
const modeElementBtn = document.getElementById('modeElement');
|
||||||
const modeSelectionBtn = document.getElementById('modeSelection');
|
const modeSelectionBtn = document.getElementById('modeSelection');
|
||||||
|
const modeAreaBtn = document.getElementById('modeArea');
|
||||||
const usageTip = document.getElementById('usageTip');
|
const usageTip = document.getElementById('usageTip');
|
||||||
|
|
||||||
// 从存储中加载模糊强度
|
// 从存储中加载模糊强度
|
||||||
@@ -41,7 +42,7 @@ blurIntensitySlider.addEventListener('input', (e) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 模式切换
|
// 模式切换
|
||||||
[modeElementBtn, modeSelectionBtn].forEach(btn => {
|
[modeElementBtn, modeSelectionBtn, modeAreaBtn].forEach(btn => {
|
||||||
btn.addEventListener('click', () => {
|
btn.addEventListener('click', () => {
|
||||||
const mode = btn.dataset.mode;
|
const mode = btn.dataset.mode;
|
||||||
currentMode = mode;
|
currentMode = mode;
|
||||||
@@ -75,7 +76,7 @@ function updateUsageTip(mode) {
|
|||||||
3. 点击元素进行模糊<br>
|
3. 点击元素进行模糊<br>
|
||||||
4. 再次点击取消模糊
|
4. 再次点击取消模糊
|
||||||
`;
|
`;
|
||||||
} else {
|
} else if (mode === 'selection') {
|
||||||
usageTip.innerHTML = `
|
usageTip.innerHTML = `
|
||||||
<strong>文本选择模式:</strong><br>
|
<strong>文本选择模式:</strong><br>
|
||||||
1. 点击"开启模糊模式"<br>
|
1. 点击"开启模糊模式"<br>
|
||||||
@@ -83,6 +84,14 @@ function updateUsageTip(mode) {
|
|||||||
3. 点击浮动按钮模糊文本<br>
|
3. 点击浮动按钮模糊文本<br>
|
||||||
4. 可多次选择和模糊
|
4. 可多次选择和模糊
|
||||||
`;
|
`;
|
||||||
|
} else if (mode === 'area') {
|
||||||
|
usageTip.innerHTML = `
|
||||||
|
<strong>区域模式:</strong><br>
|
||||||
|
1. 点击"开启模糊模式"<br>
|
||||||
|
2. 拖动鼠标绘制矩形区域<br>
|
||||||
|
3. 释放鼠标创建模糊区域<br>
|
||||||
|
4. 点击区域恢复
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -136,7 +136,7 @@
|
|||||||
<div class="test-section">
|
<div class="test-section">
|
||||||
<h2>📝 测试区域 1:普通文本</h2>
|
<h2>📝 测试区域 1:普通文本</h2>
|
||||||
<div class="test-content">
|
<div class="test-content">
|
||||||
<p>这是一段普通的文本内容,你可以点击这段文字来测试模糊功能。</p>
|
<p>这是一段普通的文本内容,你可以点击这段文字来测试模糊功能。这是一段普通的文本内容,你可以点击这段文字来测试模糊功能。这是一段普通的文本内容,你可以点击这段文字来测试模糊功能。</p>
|
||||||
<p>模糊功能应该可以立即生效,不需要屏幕录制或分享。</p>
|
<p>模糊功能应该可以立即生效,不需要屏幕录制或分享。</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user