// ==UserScript==
// @name 滚动条及顶部底部按钮
// @namespace https://gf.qytechs.cn/
// @version 1.1
// @description 在任何网页顶部显示滚动进度条,并提供滚动到顶部和底部的按钮,优化性能,减少卡顿现象。
// @author Leo
// @match *://*/*
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// 缓存DOM元素
const progressBar = document.createElement('div');
const bar = document.createElement('div');
const scrollBtns = document.createElement("div");
// 初始化样式
const initStyles = () => {
progressBar.id = 'progress';
progressBar.style.pointerEvents = 'none';
document.body.insertBefore(progressBar, document.body.firstChild);
bar.className = 'bar';
Object.assign(bar.style, {
position: 'fixed',
zIndex: '999999999',
top: '0',
left: '0',
width: '0%',
height: '2px',
background: 'linear-gradient(90deg, #03a9f4, #f441a5)',
boxShadow: '0 0 40px #03a9f4, 0 0 50px #f441a5, 0 0 60px #03a9f4',
borderRadius: '0.5em',
transition: 'width 0.2s ease'
});
progressBar.appendChild(bar);
scrollBtns.className = "goto_top_end";
Object.assign(scrollBtns.style, {
position: "fixed",
bottom: "10px",
right: "5rem",
zIndex: "1000000000",
display: "flex",
flexDirection: "row",
alignItems: "center"
});
document.body.appendChild(scrollBtns);
};
// 获取页面滚动信息
const getScrollInfo = () => ({
scrollTop: window.pageYOffset || document.documentElement.scrollTop,
pageHeight: Math.max(document.body.scrollHeight, document.documentElement.scrollHeight),
clientHeight: window.innerHeight || document.documentElement.clientHeight
});
// 更新进度条
const updateProgress = () => {
const { scrollTop, pageHeight, clientHeight } = getScrollInfo();
const maxScroll = pageHeight - clientHeight;
const progress = maxScroll > 0 ? (scrollTop / maxScroll) * 100 : 0;
const newWidth = `${Math.min(progress, 100)}%`;
if (bar.style.width !== newWidth) {
bar.style.width = newWidth;
}
};
// 创建滚动按钮
const createScrollButton = (text, onClick) => {
const button = document.createElement("button");
button.innerText = text;
Object.assign(button.style, {
padding: '10px',
marginLeft: '10px',
cursor: 'pointer',
backgroundColor: '#0005',
color: '#eee',
border: 'none',
borderRadius: '5px',
fontSize: '16px'
});
button.onclick = onClick;
return button;
};
// 创建滚动到顶部和底部的按钮
const createScrollButtons = () => {
const fragment = document.createDocumentFragment();
const toTop = createScrollButton("⬆️顶部", () => {
window.scrollTo({ top: 0, behavior: "smooth" });
});
const toEnd = createScrollButton("⬇️底部", () => {
const { clientHeight, pageHeight } = getScrollInfo();
window.scrollTo({ top: pageHeight - clientHeight, behavior: "smooth" });
});
fragment.appendChild(toTop);
fragment.appendChild(toEnd);
scrollBtns.appendChild(fragment);
};
// 页面加载时初始化
const init = () => {
initStyles();
updateProgress();
createScrollButtons();
};
window.addEventListener('load', init, { once: true });
// 监听滚动事件,使用 requestAnimationFrame 和 passive
const onScroll = () => {
requestAnimationFrame(updateProgress);
};
window.addEventListener('scroll', onScroll, { passive: true });
// 移除事件监听器
const cleanup = () => {
window.removeEventListener('scroll', onScroll);
};
window.addEventListener('beforeunload', cleanup, { once: true });
})();