Greasy Fork is available in English.
页面中只要有 <p> 标签,则提供竖直滑块调节字体大小并设置为 serif 字体;长按 2 秒页面任意位置显示悬浮面板,兼容移动端。
// ==UserScript==
// @name 阅读助手
// @namespace http://tampermonkey.net/
// @version 1.0
// @description 页面中只要有 <p> 标签,则提供竖直滑块调节字体大小并设置为 serif 字体;长按 2 秒页面任意位置显示悬浮面板,兼容移动端。
// @author qwen3
// @match *://*/*
// @grant none
// @license MIT
// ==/UserScript==
(function () {
'use strict';
// == 判断是否有 <p> 标签 ==
function hasParagraphs() {
return document.querySelectorAll('p').length > 0;
}
// == 创建全屏按钮 ==
const fullscreenBtn = document.createElement('div');
fullscreenBtn.textContent = '⛶ 全屏';
Object.assign(fullscreenBtn.style, {
position: 'fixed',
bottom: '20px',
right: '20px',
zIndex: '99999',
backgroundColor: '#007bff',
color: 'white',
padding: '14px 18px',
borderRadius: '8px',
cursor: 'pointer',
boxShadow: '0 2px 8px rgba(0,0,0,0.3)',
fontFamily: 'Arial, sans-serif',
fontSize: '16px',
transition: 'opacity 0.3s',
display: 'none',
textAlign: 'center'
});
document.body.appendChild(fullscreenBtn);
// == 创建竖直字体调节控件(放在按钮上面)==
const sliderContainer = document.createElement('div');
sliderContainer.style.position = 'fixed';
sliderContainer.style.bottom = '100px'; // 按钮上方
sliderContainer.style.right = '20px';
sliderContainer.style.zIndex = '99999';
sliderContainer.style.backgroundColor = '#f9f9f9';
sliderContainer.style.padding = '12px';
sliderContainer.style.borderRadius = '8px';
sliderContainer.style.boxShadow = '0 2px 8px rgba(0,0,0,0.3)';
sliderContainer.style.fontFamily= 'Arial, sans-serif';
sliderContainer.style.fontSize= '14px';
sliderContainer.style.display = 'none';
sliderContainer.style.textAlign = 'center';
const sliderLabel = document.createElement('div');
sliderLabel.textContent = 'Aa';
sliderLabel.style.fontWeight = 'bold';
sliderLabel.style.marginBottom = '6px';
const fontSizeSlider = document.createElement('input');
fontSizeSlider.type = 'range';
fontSizeSlider.min = '12';
fontSizeSlider.max = '36';
fontSizeSlider.value = '16';
fontSizeSlider.setAttribute('orient', 'vertical'); // Firefox 支持竖向
fontSizeSlider.style.appearance = 'slider-vertical'; // Webkit 浏览器支持
fontSizeSlider.style.height = '150px';
fontSizeSlider.style.width = '24px';
fontSizeSlider.style.transform = 'scaleY(-1)'; // 倒置使数值从上往下递增
fontSizeSlider.style.writingMode = 'bt-lr'; // Chrome 等兼容
sliderContainer.appendChild(sliderLabel);
sliderContainer.appendChild(fontSizeSlider);
document.body.appendChild(sliderContainer);
// == 注入样式,仅修改 <p> 的字体 ==
const fontStyles = document.createElement('style');
fontStyles.id = 'custom-font-style';
document.head.appendChild(fontStyles);
function applyFontStyle(fontSize) {
fontStyles.textContent = `
p {
font-family: serif !important;
font-size: ${fontSize}px !important;
line-height: 1.6 !important;
}
`;
}
// == 获取本地保存的字体大小 ==
const FONT_SIZE_KEY = 'custom_font_size_v2';
let currentFontSize = parseInt(localStorage.getItem(FONT_SIZE_KEY)) || 16;
fontSizeSlider.value = currentFontSize;
if (hasParagraphs()) {
applyFontStyle(currentFontSize);
}
// == 滑块事件监听 ==
fontSizeSlider.addEventListener('input', function () {
const newSize = parseInt(this.value);
currentFontSize = newSize;
applyFontStyle(newSize);
localStorage.setItem(FONT_SIZE_KEY, newSize.toString());
});
// == 长按逻辑:2秒触发显示面板 ==
let longPressTimer = null;
// 防止误操作输入框等
function shouldIgnoreTarget(target) {
return ['INPUT', 'TEXTAREA', 'BUTTON', 'SELECT'].includes(target.tagName);
}
function startLongPress(e) {
if (shouldIgnoreTarget(e.target)) return;
longPressTimer = setTimeout(() => {
togglePanel(true);
}, 600);
}
function stopLongPress() {
clearTimeout(longPressTimer);
}
// 添加鼠标事件(桌面)
document.addEventListener('mousedown', startLongPress);
document.addEventListener('mouseup', stopLongPress);
document.addEventListener('mouseleave', stopLongPress);
// 添加触摸事件(移动端)
document.addEventListener('touchstart', startLongPress, { passive: true });
document.addEventListener('touchend', stopLongPress);
document.addEventListener('touchcancel', stopLongPress);
// == 显示/隐藏面板函数 ==
function togglePanel(show = false) {
const isVisible = fullscreenBtn.style.display === 'block';
const shouldShow = show ? true : !isVisible;
fullscreenBtn.style.display = shouldShow ? 'block' : 'none';
sliderContainer.style.display = shouldShow ? 'block' : 'none';
}
// == 点击外部区域关闭面板 ==
document.addEventListener('click', (e) => {
const isClickInside =
e.target === fullscreenBtn ||
fullscreenBtn.contains(e.target) ||
e.target === sliderContainer ||
sliderContainer.contains(e.target);
if (!isClickInside) {
fullscreenBtn.style.display = 'none';
sliderContainer.style.display = 'none';
}
});
// == 全屏切换功能 ==
fullscreenBtn.addEventListener('click', () => {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen()
.catch(err => console.error('全屏请求失败:', err));
} else {
document.exitFullscreen();
}
});
})();