在鼠标划过文本时显示悬浮放大的效果,带有亚克力模糊背景。提供更多个性化设置选项。
- // ==UserScript==
- // @name 最美字迹放大镜
- // @version 1.0
- // @description 在鼠标划过文本时显示悬浮放大的效果,带有亚克力模糊背景。提供更多个性化设置选项。
- // @author hiisme
- // @match *://*/*
- // @grant GM_registerMenuCommand
- // @grant GM_setValue
- // @grant GM_getValue
- // @namespace https://greasyfork.org/users/217852
- // ==/UserScript==
- (async () => {
- 'use strict';
- // 默认设置
- const defaultSettings = {
- fontSize: GM_getValue('fontSize', '24px'),
- textColor: GM_getValue('textColor', '#000000'),
- borderColor: GM_getValue('borderColor', '#ccc'),
- transitionDuration: GM_getValue('transitionDuration', '0.3s'),
- acrylicBlur: GM_getValue('acrylicBlur', true),
- noBorder: GM_getValue('noBorder', false),
- textOpacity: GM_getValue('textOpacity', 1),
- backgroundOpacity: GM_getValue('backgroundOpacity', 0.2),
- acrylicStrength: GM_getValue('acrylicStrength', 10),
- fontWeight: GM_getValue('fontWeight', 'normal')
- };
- let settings = { ...defaultSettings };
- // 创建悬浮放大的文本容器
- const zoomBox = document.createElement('div');
- Object.assign(zoomBox.style, {
- position: 'absolute',
- padding: '5px',
- color: settings.textColor,
- border: settings.noBorder ? 'none' : `1px solid ${settings.borderColor}`,
- borderRadius: '5px',
- boxShadow: '0 0 10px rgba(0, 0, 0, 0.2)',
- pointerEvents: 'none',
- zIndex: '10000',
- display: 'none',
- fontSize: settings.fontSize,
- fontWeight: settings.fontWeight,
- transition: `transform ${settings.transitionDuration} ease-out, opacity ${settings.transitionDuration} ease-out`,
- transform: 'scale(0.9)',
- opacity: settings.textOpacity,
- backgroundColor: `rgba(255, 255, 255, ${settings.backgroundOpacity})`,
- backdropFilter: settings.acrylicBlur ? `blur(${settings.acrylicStrength}px)` : 'none',
- webkitBackdropFilter: settings.acrylicBlur ? `blur(${settings.acrylicStrength}px)` : 'none'
- });
- document.body.appendChild(zoomBox);
- let currentElement = null; // 当前的元素引用
- let currentLineIndex = -1; // 当前显示的行索引
- // 获取元素的每一行文本内容
- const getTextLinesFromElement = (element) => {
- return Array.from(element.childNodes)
- .filter(node => node.nodeType === Node.TEXT_NODE || (node.nodeType === Node.ELEMENT_NODE && node.tagName.toLowerCase() === 'br'))
- .reduce((acc, node) => {
- if (node.nodeType === Node.TEXT_NODE) {
- acc.push(node.textContent.trim());
- } else if (node.nodeType === Node.ELEMENT_NODE && node.tagName.toLowerCase() === 'br') {
- acc.push('\n');
- }
- return acc;
- }, [])
- .filter(line => line.trim().length > 0);
- };
- // 显示放大的文本
- const showZoomBox = (lines, index, x, y) => {
- if (index < 0 || index >= lines.length) return;
- zoomBox.textContent = lines[index];
- zoomBox.style.left = `${x + 10}px`;
- zoomBox.style.top = `${y + 10}px`;
- zoomBox.style.display = 'block';
- requestAnimationFrame(() => {
- zoomBox.style.transform = 'scale(1)';
- zoomBox.style.opacity = settings.textOpacity;
- });
- };
- // 隐藏放大的文本
- const hideZoomBox = () => {
- zoomBox.style.transform = 'scale(0.9)';
- zoomBox.style.opacity = '0';
- zoomBox.addEventListener('transitionend', () => {
- if (currentElement === null) {
- zoomBox.style.display = 'none';
- }
- }, { once: true });
- };
- // 事件处理:被动事件监听器
- document.body.addEventListener('mouseover', (e) => {
- const lines = getTextLinesFromElement(e.target);
- if (lines.length > 0 && e.target !== currentElement) {
- currentElement = e.target;
- currentLineIndex = 0;
- showZoomBox(lines, currentLineIndex, e.pageX, e.pageY);
- }
- }, { passive: true });
- document.body.addEventListener('mousemove', (e) => {
- if (currentElement) {
- zoomBox.style.left = `${e.pageX + 10}px`;
- zoomBox.style.top = `${e.pageY + 10}px`;
- const lines = getTextLinesFromElement(currentElement);
- const index = Math.floor((e.clientY - currentElement.getBoundingClientRect().top) / 20); // 根据行高计算行索引
- if (index >= 0 && index < lines.length && index !== currentLineIndex) {
- currentLineIndex = index;
- showZoomBox(lines, currentLineIndex, e.pageX, e.pageY);
- }
- }
- }, { passive: true });
- document.body.addEventListener('mouseout', (e) => {
- if (e.target === currentElement) {
- currentElement = null;
- currentLineIndex = -1;
- hideZoomBox();
- }
- }, { passive: true });
- // 注册菜单命令,用于调整设置
- const registerMenuCommands = () => {
- GM_registerMenuCommand('设置字体大小', async () => {
- const fontSize = prompt('请输入字体大小 (例如: 24px):', settings.fontSize);
- if (fontSize) {
- settings.fontSize = fontSize;
- GM_setValue('fontSize', fontSize);
- zoomBox.style.fontSize = fontSize;
- }
- });
- GM_registerMenuCommand('设置文字颜色', async () => {
- const textColor = prompt('请输入文字颜色 (例如: #000000):', settings.textColor);
- if (textColor) {
- settings.textColor = textColor;
- GM_setValue('textColor', textColor);
- zoomBox.style.color = textColor;
- }
- });
- GM_registerMenuCommand('设置边框颜色', async () => {
- const borderColor = prompt('请输入边框颜色 (例如: #ccc):', settings.borderColor);
- if (borderColor) {
- settings.borderColor = borderColor;
- GM_setValue('borderColor', borderColor);
- zoomBox.style.border = settings.noBorder ? 'none' : `1px solid ${borderColor}`;
- }
- });
- GM_registerMenuCommand('切换边框', async () => {
- settings.noBorder = !settings.noBorder;
- GM_setValue('noBorder', settings.noBorder);
- zoomBox.style.border = settings.noBorder ? 'none' : `1px solid ${settings.borderColor}`;
- alert(`边框已${settings.noBorder ? '隐藏' : '显示'}`);
- });
- GM_registerMenuCommand('设置文本不透明度', async () => {
- const textOpacity = parseFloat(prompt('请输入文本不透明度 (0 到 1):', settings.textOpacity));
- if (textOpacity >= 0 && textOpacity <= 1) {
- settings.textOpacity = textOpacity;
- GM_setValue('textOpacity', textOpacity);
- zoomBox.style.opacity = textOpacity;
- }
- });
- GM_registerMenuCommand('设置背景不透明度', async () => {
- const backgroundOpacity = parseFloat(prompt('请输入背景不透明度 (0 到 1):', settings.backgroundOpacity));
- if (backgroundOpacity >= 0 && backgroundOpacity <= 1) {
- settings.backgroundOpacity = backgroundOpacity;
- GM_setValue('backgroundOpacity', backgroundOpacity);
- zoomBox.style.backgroundColor = `rgba(255, 255, 255, ${backgroundOpacity})`;
- }
- });
- GM_registerMenuCommand('设置亚克力模糊强度', async () => {
- const acrylicStrength = parseInt(prompt('请输入亚克力模糊强度 (像素):', settings.acrylicStrength), 10);
- if (acrylicStrength >= 0) {
- settings.acrylicStrength = acrylicStrength;
- GM_setValue('acrylicStrength', acrylicStrength);
- zoomBox.style.backdropFilter = settings.acrylicBlur ? `blur(${acrylicStrength}px)` : 'none';
- zoomBox.style.webkitBackdropFilter = settings.acrylicBlur ? `blur(${acrylicStrength}px)` : 'none';
- }
- });
- GM_registerMenuCommand('切换亚克力模糊', async () => {
- settings.acrylicBlur = !settings.acrylicBlur;
- GM_setValue('acrylicBlur', settings.acrylicBlur);
- zoomBox.style.backdropFilter = settings.acrylicBlur ? `blur(${settings.acrylicStrength}px)` : 'none';
- zoomBox.style.webkitBackdropFilter = settings.acrylicBlur ? `blur(${settings.acrylicStrength}px)` : 'none';
- alert(`亚克力模糊已${settings.acrylicBlur ? '启用' : '禁用'}`);
- });
- GM_registerMenuCommand('设置过渡时间', async () => {
- const transitionDuration = prompt('请输入过渡时间 (例如: 0.3s):', settings.transitionDuration);
- if (transitionDuration) {
- settings.transitionDuration = transitionDuration;
- GM_setValue('transitionDuration', transitionDuration);
- zoomBox.style.transition = `transform ${transitionDuration} ease-out, opacity ${transitionDuration} ease-out`;
- }
- });
- GM_registerMenuCommand('设置字体粗细', async () => {
- const fontWeight = prompt('请输入字体粗细 (例如: normal, bold):', settings.fontWeight);
- if (fontWeight) {
- settings.fontWeight = fontWeight;
- GM_setValue('fontWeight', fontWeight);
- zoomBox.style.fontWeight = fontWeight;
- }
- });
- };
- registerMenuCommands();
- })();