Automates clicks at various locations on the screen with customizable intervals
目前為
// ==UserScript==
// @name YAD Multiple Auto Clicker
// @namespace http://tampermonkey.net/
// @version 2.2
// @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;
// Load button positions and settings from localStorage
const loadButtonData = () => JSON.parse(localStorage.getItem('buttonData') || '[]');
// Save button positions and settings to localStorage
const saveButtonData = () => {
const buttonData = buttons.map(button => ({
id: button.id,
top: button.style.top,
left: button.style.left
}));
localStorage.setItem('buttonData', JSON.stringify(buttonData));
};
// Save the current running state in localStorage
const saveRunningState = () => {
localStorage.setItem('isRunning', JSON.stringify(isRunning));
};
// Load the running state from localStorage on page reload
const loadRunningState = () => {
return JSON.parse(localStorage.getItem('isRunning') || 'false');
};
// Create the main interface
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';
// Plus button to add new auto-click buttons
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'; // Green background
plusButton.style.border = 'none';
plusButton.style.color = 'transparent';
plusButton.style.textShadow = '0 0 0 white';
plusButton.style.borderRadius = '5px';
mainInterface.appendChild(plusButton);
// Start/Stop button
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'; // Blue background
startStopButton.style.border = 'none';
startStopButton.style.color = 'white';
startStopButton.style.borderRadius = '5px';
mainInterface.appendChild(startStopButton);
// Reset button
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'; // Red background
resetButton.style.border = 'none';
resetButton.style.color = 'transparent';
resetButton.style.textShadow = '0 0 0 white';
resetButton.style.borderRadius = '5px';
mainInterface.appendChild(resetButton);
document.body.appendChild(mainInterface);
// Plus button functionality
plusButton.addEventListener('click', () => {
createAutoClickButton();
});
// Start/Stop button functionality
startStopButton.addEventListener('click', () => {
isRunning = !isRunning;
saveRunningState();
if (isRunning) {
startStopButton.textContent = '🛑';
startAutoClick();
} else {
startStopButton.textContent = '👆';
stopAutoClick();
}
});
// Reset button functionality
resetButton.addEventListener('click', () => {
buttons.forEach(button => button.remove());
buttons = [];
localStorage.removeItem('buttonData');
buttonId = 1;
stopAutoClick();
startStopButton.textContent = '👆';
saveRunningState();
});
// Function to create a new auto-click button
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'; // Ensure text is visible
document.body.appendChild(autoButton);
makeDraggable(autoButton);
buttons.push(autoButton);
saveButtonData();
// Open settings modal on right-click
autoButton.addEventListener('contextmenu', (e) => {
e.preventDefault();
openSettingsModal(autoButton);
});
}
// Function to make the buttons draggable
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 to open settings modal
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'; // Make it more compact
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.textAlign = 'center';
title.style.fontSize = '18px';
modal.appendChild(title);
const form = document.createElement('form');
form.style.display = 'flex';
form.style.flexDirection = 'column';
form.style.gap = '10px';
modal.appendChild(form);
const createInputField = (labelText, inputType, inputValue) => {
const fieldWrapper = document.createElement('div');
fieldWrapper.style.display = 'flex';
fieldWrapper.style.flexDirection = 'column';
const label = document.createElement('label');
label.textContent = labelText;
label.style.fontSize = '14px';
label.style.color = '#555';
label.style.marginBottom = '5px';
fieldWrapper.appendChild(label);
const input = document.createElement('input');
input.type = inputType;
input.value = inputValue;
input.style.padding = '8px';
input.style.border = '1px solid #ccc';
input.style.borderRadius = '4px';
input.style.fontSize = '14px';
fieldWrapper.appendChild(input);
return { fieldWrapper, input };
};
const intervalField = createInputField('Interval (ms):', 'number', 1000);
const clicksField = createInputField('Number of clicks:', 'number', 1);
form.appendChild(intervalField.fieldWrapper);
form.appendChild(clicksField.fieldWrapper);
const buttonWrapper = document.createElement('div');
buttonWrapper.style.display = 'flex';
buttonWrapper.style.justifyContent = 'center';
buttonWrapper.style.marginTop = '15px';
modal.appendChild(buttonWrapper);
const saveButton = document.createElement('button');
saveButton.textContent = 'Save';
saveButton.style.padding = '8px 16px';
saveButton.style.backgroundColor = '#007bff';
saveButton.style.color = 'white';
saveButton.style.border = 'none';
saveButton.style.borderRadius = '4px';
saveButton.style.cursor = 'pointer';
buttonWrapper.appendChild(saveButton);
const closeButton = document.createElement('button');
closeButton.textContent = 'Close';
closeButton.style.padding = '8px 16px';
closeButton.style.backgroundColor = '#dc3545';
closeButton.style.color = 'white';
closeButton.style.border = 'none';
closeButton.style.borderRadius = '4px';
closeButton.style.cursor = 'pointer';
buttonWrapper.appendChild(closeButton);
document.body.appendChild(modal);
saveButton.addEventListener('click', (e) => {
e.preventDefault();
button.dataset.interval = intervalField.input.value;
button.dataset.clicks = clicksField.input.value;
modal.remove();
});
closeButton.addEventListener('click', (e) => {
e.preventDefault();
modal.remove();
});
}
// Function to simulate real auto-clicks on elements
function autoClick(button) {
const rect = button.getBoundingClientRect();
button.style.visibility = 'hidden';
const elemUnderButton = document.elementFromPoint(
rect.left + rect.width / 2,
rect.top + rect.height / 2
);
button.style.visibility = 'visible';
if (elemUnderButton) {
const interval = button.dataset.interval ? parseInt(button.dataset.interval) : 1000;
const clicks = button.dataset.clicks ? parseInt(button.dataset.clicks) : 1;
for (let i = 0; i < clicks; i++) {
simulateClick(elemUnderButton);
}
// Delay between clicks
return new Promise(resolve => setTimeout(resolve, interval));
}
}
// Function to simulate clicks, including handling iframes and shadow DOMs
function simulateClick(target) {
const eventNames = ['mousedown', 'mouseup', 'click'];
eventNames.forEach(eventName => {
const event = new MouseEvent(eventName, {
bubbles: true,
cancelable: true,
view: window
});
target.dispatchEvent(event);
});
// Handle iframes
if (target.tagName === 'IFRAME') {
const iframeDoc = target.contentDocument || target.contentWindow.document;
const clickableElement = iframeDoc.querySelector('selector'); // Update this selector for specific iframe content
clickableElement?.click();
}
// Handle Shadow DOM
if (target.shadowRoot) {
const clickableElement = target.shadowRoot.querySelector('selector'); // Update this selector for Shadow DOM
clickableElement?.click();
}
}
// Function to start auto-clicking in sequence
async function startAutoClick() {
if (buttons.length === 0) return;
while (isRunning) {
for (let button of buttons) {
await autoClick(button);
}
}
}
// Function to stop auto-clicking
function stopAutoClick() {
isRunning = false;
}
// Initialize the script on page load
const buttonData = loadButtonData();
buttonData.forEach(data => createAutoClickButton(data));
isRunning = loadRunningState();
if (isRunning) {
startStopButton.textContent = '🛑';
startAutoClick();
}
})();