Via加载进度条

基于王秋儿发色的动态加载进度条 | #B5C7E5→#C8BFE7

// ==UserScript==
// @name         Via加载进度条
// @namespace    https://viayoo.com/
// @version      2.3.3
// @description  基于王秋儿发色的动态加载进度条 | #B5C7E5→#C8BFE7
// @author       是小白呀 & DeepSeek & Grok
// @match        *://*/*
// @license      MIT
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';
    
    const LOADER_THEME = {
        PRIMARY: '#B5C7E5',
        SECONDARY: '#C8BFE7',
        GLOW: '#D4B1FF',
        DURATION: 380,
        HEIGHT: 2.5, // 调整为2.5px,推荐值
        HIDE_DELAY: 200
    };

    const createLoader = () => {
        const existing = document.getElementById('via-loader');
        if (existing) existing.remove();

        const loader = document.createElement('div');
        loader.id = 'via-loader';
        Object.assign(loader.style, {
            position: 'fixed',
            top: '0',
            left: '0',
            width: '0%',
            height: `${LOADER_THEME.HEIGHT}px`,
            zIndex: '99999',
            background: `linear-gradient(135deg,
                ${LOADER_THEME.PRIMARY} 25%,
                ${LOADER_THEME.SECONDARY} 50%,
                ${LOADER_THEME.GLOW} 75%,
                ${LOADER_THEME.PRIMARY} 100%
            )`,
            backgroundSize: '200% 100%',
            transition: `width ${LOADER_THEME.DURATION}ms ease-out,
                        opacity ${LOADER_THEME.DURATION / 2}ms ease-in`,
            pointerEvents: 'none',
            boxShadow: `0 2px 6px ${LOADER_THEME.SECONDARY}33`
        });
        
        document.documentElement.appendChild(loader);
        return loader;
    };

    class LoadingSystem {
        constructor() {
            this.loader = createLoader();
            this.pageLoadStatus = false;
            this.initLoader();
        }

        initLoader() {
            this.setupLoadingSimulator();
            this.setupSPAListener();
        }

        setupLoadingSimulator() {
            let progress = 0;
            const baseSpeed = 0.05;
            const networkFactor = navigator.connection 
                ? Math.min(navigator.connection.downlink / 5, 1)
                : 1;

            const animate = () => {
                if (this.pageLoadStatus) return;
                
                const dynamicSpeed = baseSpeed * 
                                   Math.pow(1 - progress / 100, 0.7) *
                                   (0.8 + Math.random() * 0.4) * 
                                   networkFactor;
                
                progress = Math.min(progress + dynamicSpeed * 100, 99.9);
                this.loader.style.width = `${progress}%`;
                this.loader.style.backgroundPositionX = 
                    `${Math.sin(Date.now()/800)*50 + 50}%`;
                
                requestAnimationFrame(animate);
            };
            
            animate();

            const completeHandler = () => {
                this.pageLoadStatus = true;
                this.loader.style.width = '100%';
                setTimeout(() => {
                    this.loader.style.opacity = '0';
                    setTimeout(() => this.loader.remove(), LOADER_THEME.DURATION);
                }, LOADER_THEME.HIDE_DELAY);
            };

            window.addEventListener('load', completeHandler, { once: true });
            document.addEventListener('DOMContentLoaded', () => {
                if (!this.pageLoadStatus) setTimeout(completeHandler, 1500);
            });
        }

        setupSPAListener() {
            const resetLoader = () => {
                if (this.pageLoadStatus) {
                    this.pageLoadStatus = false;
                    this.loader = createLoader();
                    this.setupLoadingSimulator();
                }
            };

            const wrapHistory = (method) => {
                const orig = history[method];
                return function() {
                    const result = orig.apply(this, arguments);
                    resetLoader();
                    return result;
                };
            };
            
            history.pushState = wrapHistory('pushState');
            history.replaceState = wrapHistory('replaceState');
            window.addEventListener('popstate', resetLoader);
        }
    }

    // 初始化
    const init = () => {
        if (document.getElementById('via-loader')) return;
        new LoadingSystem();
    };

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        setTimeout(init, 0);
    }
})();