Greasy Fork

Greasy Fork is available in English.

滚动条及顶部底部按钮

在任何网页顶部显示滚动进度条,并提供滚动到顶部和底部的按钮,优化性能,减少卡顿现象。

当前为 2024-10-06 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         滚动条及顶部底部按钮
// @namespace    http://greasyfork.icu/
// @version      1.0
// @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);

    // 监听滚动事件,使用 requestAnimationFrame 和 passive
    const onScroll = () => {
        requestAnimationFrame(updateProgress);
    };

    window.addEventListener('scroll', onScroll, { passive: true });

    // 移除事件监听器
    const cleanup = () => {
        window.removeEventListener('scroll', onScroll);
    };

    window.addEventListener('beforeunload', cleanup);

})();