定时关闭网页

页面加载弹出滑块设置倒计时,小球显示秒级倒计时+环形进度条,支持拖拽、点击修改时间、暂停/继续

目前為 2025-08-18 提交的版本,檢視 最新版本

// ==UserScript==
// @name         定时关闭网页
// @namespace    https://github.com/yingchen6
// @version      1.5
// @description  页面加载弹出滑块设置倒计时,小球显示秒级倒计时+环形进度条,支持拖拽、点击修改时间、暂停/继续
// @author       yingchen6
// @match        *://*/*
// @grant        GM_addStyle
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    let timerId = null;
    let remainingSeconds = 0;
    let totalSeconds = 0;
    let ball = null;
    let canvas = null;
    let paused = false;

    function formatTime(seconds) {
        const m = Math.floor(seconds / 60);
        const s = seconds % 60;
        return `${m}:${s.toString().padStart(2,'0')}`;
    }

    function createBall(minutes) {
        totalSeconds = remainingSeconds = minutes * 60;
        paused = false;

        if (ball) ball.remove();

        ball = document.createElement("div");
        ball.id = "timer-ball";
        ball.style.position = "fixed";
        ball.style.top = "20px";
        ball.style.left = "20px";
        ball.style.width = "120px";
        ball.style.height = "120px";
        ball.style.borderRadius = "50%";
        ball.style.zIndex = "999999";
        ball.style.cursor = "grab";
        ball.style.display = "flex";
        ball.style.justifyContent = "center";
        ball.style.alignItems = "center";
        ball.style.userSelect = "none";
        ball.style.background = "radial-gradient(circle at 30% 30%, #4facfe, #00f2fe)";
        ball.style.boxShadow = "0 8px 25px rgba(0,0,0,0.5)";
        document.body.appendChild(ball);

        canvas = document.createElement("canvas");
        canvas.width = 120;
        canvas.height = 120;
        canvas.style.position = "absolute";
        canvas.style.top = "0";
        canvas.style.left = "0";
        ball.appendChild(canvas);

        const label = document.createElement("div");
        label.id = "timer-label";
        label.style.position = "absolute";
        label.style.color = "white";
        label.style.fontWeight = "bold";
        label.style.fontSize = "18px";
        ball.appendChild(label);

        const pauseBtn = document.createElement("div");
        pauseBtn.id = "pause-btn";
        pauseBtn.style.position = "absolute";
        pauseBtn.style.bottom = "5px";
        pauseBtn.style.fontSize = "12px";
        pauseBtn.style.color = "#fff";
        pauseBtn.style.background = "rgba(0,0,0,0.3)";
        pauseBtn.style.borderRadius = "6px";
        pauseBtn.style.padding = "2px 6px";
        pauseBtn.style.cursor = "pointer";
        pauseBtn.textContent = "暂停";
        ball.appendChild(pauseBtn);

        pauseBtn.addEventListener("click", (e)=>{
            e.stopPropagation();
            paused = !paused;
            pauseBtn.textContent = paused ? "继续" : "暂停";
        });

        // 拖拽 + 点击判定
        let isDown = false;
        let isDragging = false;
        let startX = 0, startY = 0;
        let downTime = 0;

        ball.addEventListener("mousedown", (e)=>{
            isDown = true;
            isDragging = false;
            startX = e.clientX;
            startY = e.clientY;
            downTime = Date.now();
            ball.style.cursor="grabbing";
        });

        document.addEventListener("mousemove", (e)=>{
            if(!isDown) return;
            const dx = e.clientX - startX;
            const dy = e.clientY - startY;
            if(Math.sqrt(dx*dx + dy*dy) > 5){
                isDragging = true;
            }
            if(isDragging){
                ball.style.left = e.clientX - startX + "px";
                ball.style.top = e.clientY - startY + "px";
            }
        });

        document.addEventListener("mouseup", (e)=>{
            if(!isDown) return;
            isDown = false;
            ball.style.cursor = "grab";
            const elapsed = Date.now() - downTime;
            if(!isDragging && elapsed < 400){
                showTimeSetting();
            }
        });

        startCountdown(minutes);
    }

    function startCountdown(minutes){
        totalSeconds = remainingSeconds = minutes*60;
        paused = false;

        if(timerId) clearInterval(timerId);

        timerId = setInterval(()=>{
            if(!paused){
                remainingSeconds--;
                if(remainingSeconds <= 0){
                    clearInterval(timerId);
                    window.location.href = "about:blank";
                    return;
                }
                const label = document.getElementById("timer-label");
                label.textContent = formatTime(remainingSeconds);

                const ctx = canvas.getContext("2d");
                ctx.clearRect(0,0,canvas.width,canvas.height);

                // 背景圆
                ctx.beginPath();
                ctx.arc(canvas.width/2,canvas.height/2,50,0,2*Math.PI);
                ctx.strokeStyle = "rgba(255,255,255,0.2)";
                ctx.lineWidth = 10;
                ctx.stroke();

                // 进度圆
                const fraction = remainingSeconds / totalSeconds;
                ctx.beginPath();
                ctx.arc(canvas.width/2,canvas.height/2,50,-Math.PI/2, -Math.PI/2 + 2*Math.PI*fraction);
                ctx.strokeStyle = "#ffd700";
                ctx.lineWidth = 10;
                ctx.lineCap = "round";
                ctx.stroke();
            }
        },1000);
    }

    // 滑块设置界面
    function showTimeSetting(){
        const wrapper = document.createElement("div");
        wrapper.innerHTML = `
          <div style="display:flex;flex-direction:column;align-items:center;gap:10px;">
            <input id="timeRange" type="range" min="1" max="180" step="1" value="30" style="width:90%;">
            <span id="timeLabel">30 分钟</span>
            <small>拖动滑块选择时间 (1 ~ 180 分钟)</small>
          </div>
        `;
        swal({
            title: "请选择倒计时",
            content: wrapper,
            buttons: { cancel: "取消", confirm: "确定" }
        }).then((confirm)=>{
            if(!confirm) return;
            const minutes = parseInt(document.getElementById("timeRange").value);
            createBall(minutes);
        });

        const range = wrapper.querySelector("#timeRange");
        const label = wrapper.querySelector("#timeLabel");
        range.addEventListener("input", ()=>{ label.textContent = range.value+" 分钟"; });
    }

    // 页面加载完立即弹出滑块设置
    window.addEventListener("load", ()=>{
        showTimeSetting();
    });

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址