YAD Multiple Auto Clicker

Automates clicks at various locations on the screen with customizable intervals

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

// ==UserScript==
// @name         YAD Multiple Auto Clicker
// @namespace    http://tampermonkey.net/
// @version      1.9
// @description  Automates clicks at various locations on the screen with customizable intervals
// @author       YAD
// @license      MIT
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    let buttons = [];
    let buttonId = 1;
    let isRunning = false;

    const loadButtonData = () => JSON.parse(localStorage.getItem('buttonData') || '[]');
    const saveButtonData = () => {
        const buttonData = buttons.map(button => ({
            id: button.id,
            top: button.style.top,
            left: button.style.left,
            interval: button.dataset.interval || 1000,
            clicks: button.dataset.clicks || 1
        }));
        localStorage.setItem('buttonData', JSON.stringify(buttonData));
    };
    const saveRunningState = () => {
        localStorage.setItem('isRunning', JSON.stringify(isRunning));
    };
    const loadRunningState = () => {
        return JSON.parse(localStorage.getItem('isRunning') || 'false');
    };

    const mainInterface = document.createElement('div');
    mainInterface.style.position = 'fixed';
    mainInterface.style.right = '10px';
    mainInterface.style.top = '50%';
    mainInterface.style.transform = 'translateY(-50%)';
    mainInterface.style.zIndex = '9999';
    mainInterface.style.pointerEvents = 'none';

    const plusButton = document.createElement('button');
    plusButton.textContent = '➕';
    plusButton.style.display = 'block';
    plusButton.style.padding = '10px';
    plusButton.style.marginBottom = '5px';
    plusButton.style.fontSize = '16px';
    plusButton.style.cursor = 'pointer';
    plusButton.style.backgroundColor = '#28a745';
    plusButton.style.border = 'none';
    plusButton.style.color = 'transparent';
    plusButton.style.textShadow = '0 0 0 white';
    plusButton.style.borderRadius = '5px';
    plusButton.style.pointerEvents = 'all';
    mainInterface.appendChild(plusButton);

    const startStopButton = document.createElement('button');
    startStopButton.textContent = '👆';
    startStopButton.style.display = 'block';
    startStopButton.style.padding = '10px';
    startStopButton.style.marginBottom = '5px';
    startStopButton.style.fontSize = '16px';
    startStopButton.style.cursor = 'pointer';
    startStopButton.style.backgroundColor = '#007bff';
    startStopButton.style.border = 'none';
    startStopButton.style.color = 'white';
    startStopButton.style.borderRadius = '5px';
    startStopButton.style.pointerEvents = 'all';
    mainInterface.appendChild(startStopButton);

    const resetButton = document.createElement('button');
    resetButton.textContent = '♻️';
    resetButton.style.display = 'block';
    resetButton.style.padding = '10px';
    resetButton.style.fontSize = '16px';
    resetButton.style.cursor = 'pointer';
    resetButton.style.backgroundColor = '#dc3545';
    resetButton.style.border = 'none';
    resetButton.style.color = 'transparent';
    resetButton.style.textShadow = '0 0 0 white';
    resetButton.style.borderRadius = '5px';
    resetButton.style.pointerEvents = 'all';
    mainInterface.appendChild(resetButton);

    document.body.appendChild(mainInterface);

    plusButton.addEventListener('click', () => {
        createAutoClickButton();
    });

    startStopButton.addEventListener('click', () => {
        isRunning = !isRunning;
        saveRunningState();
        if (isRunning) {
            startStopButton.textContent = '🛑';
            startAutoClick();
        } else {
            startStopButton.textContent = '👆';
            stopAutoClick();
        }
    });

    resetButton.addEventListener('click', () => {
        buttons.forEach(button => button.remove());
        buttons = [];
        localStorage.removeItem('buttonData');
        buttonId = 1;
        stopAutoClick();
        startStopButton.textContent = '👆';
    });

    function createAutoClickButton(buttonData = null) {
        const autoButton = document.createElement('div');
        autoButton.id = buttonId++;
        autoButton.textContent = autoButton.id;
        autoButton.style.width = '50px';
        autoButton.style.height = '50px';
        autoButton.style.borderRadius = '50%';
        autoButton.style.backgroundColor = '#ff0000cc';
        autoButton.style.position = 'absolute';
        autoButton.style.top = buttonData?.top || '50%';
        autoButton.style.left = buttonData?.left || '50%';
        autoButton.style.display = 'flex';
        autoButton.style.alignItems = 'center';
        autoButton.style.justifyContent = 'center';
        autoButton.style.cursor = 'pointer';
        autoButton.style.zIndex = '9999';
        autoButton.style.color = 'white';
        autoButton.style.pointerEvents = 'all';
        document.body.appendChild(autoButton);
        makeDraggable(autoButton);

        autoButton.dataset.interval = buttonData?.interval || 1000;
        autoButton.dataset.clicks = buttonData?.clicks || 1;

        buttons.push(autoButton);

        autoButton.addEventListener('contextmenu', (e) => {
            e.preventDefault();
            openSettingsModal(autoButton);
        });

        autoButton.addEventListener('click', (e) => {
            e.stopPropagation();
        });
    }

    function makeDraggable(element) {
        let posX = 0, posY = 0, mouseX = 0, mouseY = 0;
        element.onmousedown = function (e) {
            e.preventDefault();
            mouseX = e.clientX;
            mouseY = e.clientY;
            document.onmousemove = moveElement;
            document.onmouseup = stopMovingElement;
        };

        function moveElement(e) {
            posX = mouseX - e.clientX;
            posY = mouseY - e.clientY;
            mouseX = e.clientX;
            mouseY = e.clientY;
            element.style.top = (element.offsetTop - posY) + 'px';
            element.style.left = (element.offsetLeft - posX) + 'px';
        }

        function stopMovingElement() {
            document.onmouseup = null;
            document.onmousemove = null;
            saveButtonData();
        }
    }

    function openSettingsModal(button) {
        const modal = document.createElement('div');
        modal.style.position = 'fixed';
        modal.style.top = '50%';
        modal.style.left = '50%';
        modal.style.transform = 'translate(-50%, -50%)';
        modal.style.zIndex = '10000';
        modal.style.padding = '15px';
        modal.style.backgroundColor = '#fff';
        modal.style.borderRadius = '8px';
        modal.style.boxShadow = '0px 4px 12px rgba(0, 0, 0, 0.1)';
        modal.style.width = '300px';
        modal.style.fontFamily = 'Arial, sans-serif';

        const title = document.createElement('h3');
        title.textContent = 'Settings';
        title.style.marginTop = '0';
        title.style.marginBottom = '15px';
        title.style.color = '#333';
        title.style.fontSize = '18px';
        modal.appendChild(title);

        const form = document.createElement('form');
        modal.appendChild(form);

        const createInputField = (labelText, type, inputValue) => {
            const fieldWrapper = document.createElement('div');
            fieldWrapper.style.marginBottom = '10px';

            const label = document.createElement('label');
            label.textContent = labelText;
            label.style.fontSize = '14px';
            label.style.display = 'block';
            label.style.marginBottom = '5px';
            fieldWrapper.appendChild(label);

            const input = document.createElement('input');
            input.type = type;
            input.value = inputValue;
            input.style.padding = '8px';
            input.style.fontSize = '14px';
            input.style.borderRadius = '4px';
            input.style.border = '1px solid #ccc';
            fieldWrapper.appendChild(input);

            form.appendChild(fieldWrapper);

            return input;
        };

        const intervalInput = createInputField('Click Interval (ms)', 'number', button.dataset.interval);
        const clicksInput = createInputField('Clicks per Interval', 'number', button.dataset.clicks);

        const submitButton = document.createElement('button');
        submitButton.textContent = 'Save';
        submitButton.style.padding = '10px';
        submitButton.style.borderRadius = '5px';
        submitButton.style.border = 'none';
        submitButton.style.backgroundColor = '#007bff';
        submitButton.style.color = 'white';
        submitButton.style.fontSize = '16px';
        submitButton.style.cursor = 'pointer';
        form.appendChild(submitButton);

        submitButton.addEventListener('click', (e) => {
            e.preventDefault();
            button.dataset.interval = intervalInput.value;
            button.dataset.clicks = clicksInput.value;
            document.body.removeChild(modal);
            saveButtonData();
        });

        document.body.appendChild(modal);
    }

    function simulateMouseClick(element) {
        const rect = element.getBoundingClientRect();
        const x = rect.left + (rect.width / 2);
        const y = rect.top + (rect.height / 2);

        const clickEvent = new MouseEvent('click', {
            bubbles: true,
            cancelable: true,
            clientX: x,
            clientY: y
        });

        element.dispatchEvent(clickEvent);
    }

    function startAutoClick() {
        buttons.forEach(button => {
            button.clickInterval = setInterval(() => {
                const elementAtPosition = document.elementFromPoint(
                    button.getBoundingClientRect().left + button.offsetWidth / 2,
                    button.getBoundingClientRect().top + button.offsetHeight / 2
                );

                if (elementAtPosition) {
                    for (let i = 0; i < button.dataset.clicks; i++) {
                        simulateMouseClick(elementAtPosition);
                    }
                }
            }, button.dataset.interval);
        });
    }

    function stopAutoClick() {
        buttons.forEach(button => clearInterval(button.clickInterval));
    }

    function init() {
        const buttonData = loadButtonData();
        buttonData.forEach(data => createAutoClickButton(data));

        isRunning = loadRunningState();
        if (isRunning) {
            startStopButton.textContent = '🛑';
            startAutoClick();
        }
    }

    init();
})();