// ==UserScript==
// @name 高级自动滚动控制器
// @namespace http://tampermonkey.net/
// @version 1.0
// @description 支持调节滚动速度、方向、底部行为,且面板可最小化的自动滚动工具
// @author yangwenren
// @match *://*/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
// 全局变量
let isScrolling = false;
let scrollSpeed = 5; // 滚动速度
let scrollDirection = 'down';// 滚动方向 (down/up)
let bottomJump = true; // 底部是否跳转顶部
let panelMinimized = false; // 面板是否最小化
let scrollInterval;
const MIN_SPEED = 1;
const MAX_SPEED = 20;
// 创建控制界面
function createControlPanel() {
// 主面板容器
const panel = document.createElement('div');
panel.id = 'scrollControlPanel';
panel.style.cssText = `
position: fixed;
bottom: 20px;
right: 20px;
background: rgba(255,255,255,0.95);
border: 1px solid #ccc;
border-radius: 8px;
box-shadow: 0 2px 15px rgba(0,0,0,0.2);
z-index: 999999;
font-family: Arial, sans-serif;
width: 250px;
transition: all 0.3s ease;
`;
// 标题栏(包含最小化按钮)
const titleBar = document.createElement('div');
titleBar.style.cssText = `
padding: 8px 15px;
border-bottom: 1px solid #eee;
display: flex;
justify-content: space-between;
align-items: center;
cursor: move;
`;
const title = document.createElement('h3');
title.textContent = '高级滚动控制器';
title.style.cssText = 'margin: 0; font-size: 15px;';
const minBtn = document.createElement('button');
minBtn.textContent = '−';
minBtn.style.cssText = `
width: 24px;
height: 24px;
border: none;
background: transparent;
font-size: 18px;
cursor: pointer;
line-height: 1;
padding: 0;
color: #666;
`;
minBtn.addEventListener('click', toggleMinimize);
titleBar.append(title, minBtn);
panel.appendChild(titleBar);
// 内容区域(可折叠)
const contentArea = document.createElement('div');
contentArea.id = 'panelContent';
contentArea.style.padding = '15px';
// 速度控制
const speedDiv = document.createElement('div');
speedDiv.style.marginBottom = '12px';
const speedLabel = document.createElement('label');
speedLabel.textContent = `滚动速度: ${scrollSpeed}`;
speedLabel.id = 'speedLabel';
speedLabel.style.display = 'block';
speedLabel.style.marginBottom = '5px';
const speedSlider = document.createElement('input');
speedSlider.type = 'range';
speedSlider.min = MIN_SPEED;
speedSlider.max = MAX_SPEED;
speedSlider.value = scrollSpeed;
speedSlider.style.width = '100%';
speedSlider.addEventListener('input', function() {
scrollSpeed = parseInt(this.value);
document.getElementById('speedLabel').textContent = `滚动速度: ${scrollSpeed}`;
if (isScrolling) updateScrollInterval();
});
speedDiv.append(speedLabel, speedSlider);
contentArea.appendChild(speedDiv);
// 方向控制
const directionDiv = document.createElement('div');
directionDiv.style.marginBottom = '12px';
directionDiv.style.display = 'flex';
directionDiv.style.alignItems = 'center';
directionDiv.style.gap = '10px';
const directionLabel = document.createElement('label');
directionLabel.textContent = '滚动方向:';
directionLabel.style.width = '80px';
const directionSelect = document.createElement('select');
directionSelect.style.flex = '1';
directionSelect.innerHTML = `
`;
directionSelect.value = scrollDirection;
directionSelect.addEventListener('change', function() {
scrollDirection = this.value;
if (isScrolling) updateScrollInterval();
});
directionDiv.append(directionLabel, directionSelect);
contentArea.appendChild(directionDiv);
// 底部跳转控制
const jumpDiv = document.createElement('div');
jumpDiv.style.marginBottom = '15px';
jumpDiv.style.display = 'flex';
jumpDiv.style.alignItems = 'center';
jumpDiv.style.gap = '10px';
const jumpLabel = document.createElement('label');
jumpLabel.textContent = '底部行为:';
jumpLabel.style.width = '80px';
const jumpSelect = document.createElement('select');
jumpSelect.style.flex = '1';
jumpSelect.innerHTML = `
`;
jumpSelect.value = bottomJump ? 'jump' : 'reverse';
jumpSelect.addEventListener('change', function() {
bottomJump = this.value === 'jump';
if (isScrolling) updateScrollInterval();
});
jumpDiv.append(jumpLabel, jumpSelect);
contentArea.appendChild(jumpDiv);
// 控制按钮
const buttonDiv = document.createElement('div');
buttonDiv.style.display = 'flex';
buttonDiv.style.gap = '8px';
const startBtn = document.createElement('button');
startBtn.textContent = '开始滚动';
startBtn.style.cssText = `
flex: 1;
padding: 6px;
background: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
`;
const stopBtn = document.createElement('button');
stopBtn.textContent = '停止滚动';
stopBtn.style.cssText = `
flex: 1;
padding: 6px;
background: #f44336;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
`;
stopBtn.disabled = true;
startBtn.addEventListener('click', () => {
if (!isScrolling) {
startScrolling();
isScrolling = true;
startBtn.disabled = true;
stopBtn.disabled = false;
}
});
stopBtn.addEventListener('click', () => {
if (isScrolling) {
clearInterval(scrollInterval);
isScrolling = false;
startBtn.disabled = false;
stopBtn.disabled = true;
}
});
buttonDiv.append(startBtn, stopBtn);
contentArea.appendChild(buttonDiv);
panel.appendChild(contentArea);
document.body.appendChild(panel);
// 支持面板拖动
makePanelDraggable(panel, titleBar);
}
// 切换最小化/展开状态
function toggleMinimize() {
const panel = document.getElementById('scrollControlPanel');
const content = document.getElementById('panelContent');
const minBtn = panel.querySelector('button');
panelMinimized = !panelMinimized;
if (panelMinimized) {
// 最小化状态
content.style.display = 'none';
panel.style.width = 'auto';
minBtn.textContent = '+';
} else {
// 展开状态
content.style.display = 'block';
panel.style.width = '250px';
minBtn.textContent = '−';
}
}
// 使面板可拖动
function makePanelDraggable(panel, handle) {
let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
handle.onmousedown = dragMouseDown;
function dragMouseDown(e) {
e = e || window.event;
e.preventDefault();
// 获取鼠标初始位置
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
// 当鼠标移动时调用elementDrag函数
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
// 计算新的位置
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
// 设置元素新的位置
panel.style.top = (panel.offsetTop - pos2) + "px";
panel.style.left = (panel.offsetLeft - pos1) + "px";
// 清除bottom和right属性,避免冲突
panel.style.bottom = "auto";
panel.style.right = "auto";
}
function closeDragElement() {
// 停止移动
document.onmouseup = null;
document.onmousemove = null;
}
}
// 更新滚动间隔(参数变化时调用)
function updateScrollInterval() {
clearInterval(scrollInterval);
startScrolling();
}
// 滚动逻辑实现
function startScrolling() {
scrollInterval = setInterval(() => {
const currentPos = window.scrollY;
const windowHeight = window.innerHeight;
const docHeight = Math.max(
document.body.scrollHeight,
document.body.offsetHeight,
document.documentElement.scrollHeight,
document.documentElement.offsetHeight
);
// 计算边界
const atBottom = currentPos + windowHeight >= docHeight - 50;
const atTop = currentPos <= 50;
let newPos;
// 根据方向计算新位置
if (scrollDirection === 'down') {
newPos = currentPos + scrollSpeed;
// 处理底部逻辑
if (atBottom) {
if (bottomJump) {
newPos = 0; // 跳转到顶部
} else {
scrollDirection = 'up'; // 反向滚动
newPos = currentPos - scrollSpeed;
}
}
} else { // 向上滚动
newPos = currentPos - scrollSpeed;
// 处理顶部逻辑
if (atTop) {
if (bottomJump) {
newPos = docHeight - windowHeight; // 跳转到底部
} else {
scrollDirection = 'down'; // 反向滚动
newPos = currentPos + scrollSpeed;
}
}
}
window.scrollTo(0, newPos);
}, 20);
}
// 初始化
createControlPanel();
})();