支持拖拽后位置记忆
Resolved#1617zhxhwyzh14Created at 21 days ago

// ==UserScript==
// @name Linux.do一键滚动到底部和顶部(支持懒加载+拖拽记忆)
// @namespace http://tampermonkey.net/
// @version 0.5
// @description 实现网页滚动到底部、顶部,处理懒加载内容,支持按钮拖拽并记忆位置
// @match https://linux.do/*
// @grant none
// ==/UserScript==

(function() {
'use strict';

// ===== 工具:读取/保存位置 =====
function savePosition(key, top, right) {
    localStorage.setItem(key, JSON.stringify({ top, right }));
}

function loadPosition(key, defaultTop, defaultRight) {
    const data = localStorage.getItem(key);
    if (data) {
        try {
            const pos = JSON.parse(data);
            return {
                top: pos.top,
                right: pos.right
            };
        } catch (e) {}
    }
    return { top: defaultTop, right: defaultRight };
}

// ===== 创建按钮 =====
function createButton(text, onClick, defaultTop, storageKey) {
    const button = document.createElement('button');
    button.textContent = text;

    const pos = loadPosition(storageKey, defaultTop, 20);

    button.style.cssText = `
        position: fixed;
        right: ${pos.right}px;
        top: ${pos.top}px;
        padding: 10px;
        z-index: 9999;
        background-color: #4CAF50;
        color: white;
        border: none;
        border-radius: 5px;
        cursor: move;
        opacity: 0.7;
        transition: opacity 0.3s;
    `;

    button.addEventListener('mouseover', () => button.style.opacity = '1');
    button.addEventListener('mouseout', () => button.style.opacity = '0.7');

    button.addEventListener('click', onClick);

    makeDraggable(button, storageKey);

    return button;
}

// ===== 拖拽 + 保存 =====
function makeDraggable(element, storageKey) {
    let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;

    element.onmousedown = dragMouseDown;

    function dragMouseDown(e) {
        e.preventDefault();
        pos3 = e.clientX;
        pos4 = e.clientY;

        document.onmouseup = closeDragElement;
        document.onmousemove = elementDrag;
    }

    function elementDrag(e) {
        e.preventDefault();

        pos1 = pos3 - e.clientX;
        pos2 = pos4 - e.clientY;
        pos3 = e.clientX;
        pos4 = e.clientY;

        const newTop = element.offsetTop - pos2;
        const newRight = parseInt(element.style.right) + pos1;

        element.style.top = newTop + "px";
        element.style.right = newRight + "px";
    }

    function closeDragElement() {
        document.onmouseup = null;
        document.onmousemove = null;

        // ===== 保存位置 =====
        savePosition(
            storageKey,
            element.offsetTop,
            parseInt(element.style.right)
        );
    }
}

// ===== 滚动函数 =====
function smoothScroll(toTop) {
    return new Promise((resolve) => {
        let lastScrollHeight = document.documentElement.scrollHeight;
        let scrollAttempts = 0;
        const maxScrollAttempts = 50;

        function scroll() {
            if (toTop) {
                window.scrollTo(0, 0);
            } else {
                window.scrollTo(0, document.documentElement.scrollHeight);
            }

            scrollAttempts++;

            setTimeout(() => {
                const currentScrollHeight = document.documentElement.scrollHeight;

                if (currentScrollHeight !== lastScrollHeight && scrollAttempts < maxScrollAttempts) {
                    lastScrollHeight = currentScrollHeight;
                    scroll();
                } else {
                    resolve();
                }
            }, 300);
        }

        scroll();
    });
}

// ===== 创建按钮 =====
const scrollTopButton = createButton(
    '⬆️ 顶部',
    () => smoothScroll(true),
    20,
    'scrollTopBtnPos'
);
document.body.appendChild(scrollTopButton);

const scrollBottomButton = createButton(
    '⬇️ 底部',
    () => smoothScroll(false),
    70,
    'scrollBottomBtnPos'
);
document.body.appendChild(scrollBottomButton);

})();

No data
Login to comment
Labels
Watch
Participants