Canvas Smooth Drag with Button (No Style)

在指定頁面新增按鈕,點擊時模擬平滑滑鼠拖曳(無 CSS 樣式)

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Canvas Smooth Drag with Button (No Style)
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  在指定頁面新增按鈕,點擊時模擬平滑滑鼠拖曳(無 CSS 樣式)
// @author       You
// @match        https://en.gamesaien.com/game/fruit_box/*
// @grant        none
// @license MIT
// ==/UserScript==

const COLS = 17;
const ROWS = 10;

const GRID_LEFT = 70;
const GRID_TOP = 75;
const GRID_RIGHT = 600;
const GRID_BOTTOM = 370;

const GRID_WIDTH = (GRID_RIGHT - GRID_LEFT) / (COLS - 1); // 每列間距
const GRID_HEIGHT = (GRID_BOTTOM - GRID_TOP) / (ROWS - 1); // 每行間距

(function () {
    'use strict';

    const startX = 200;
    const startY = 300;
    const endX = 800;
    const endY = 500;

    const waitForElements = setInterval(() => {
        const canvas = document.querySelector('canvas#canvas');
        const container = document.querySelector('div#animation_container');

        if (canvas && container && container.parentElement) {
            clearInterval(waitForElements);
            injectButton(container.parentElement, canvas);
            addCanvasClickLogger(canvas);
        }
    }, 500);

    function injectButton(parent, canvas) {
        const btn = document.createElement('button');
        btn.textContent = 'TEST1';
        btn.id = 'tm_test1_btn';
        parent.appendChild(btn);

        btn.addEventListener('click', async () => {
            console.log('[TEST1] 執行自動圈選');



            // 2X1
            for (let row = 0; row < 10; row++) {
                for (let col = 0; col < 16; col++) {
                    let area = getGridRangeCorners(col, row, col + 2, row + 1);
                    await simulateSmoothDrag(canvas, area.x1, area.y1, area.x2, area.y2);
                    await new Promise(resolve => setTimeout(resolve, 5));
                }
            }

            // 1x2
            for (let col = 0; col < 17; col++) {
                for (let row = 0; row < 9; row++) {
                    let area = getGridRangeCorners(col, row, col + 1, row + 2);
                    await simulateSmoothDrag(canvas, area.x1, area.y1, area.x2, area.y2);
                    await new Promise(resolve => setTimeout(resolve, 5));
                }
            }

            // 3x1
            for (let row = 0; row < 10; row++) {
                for (let col = 0; col < 15; col++) {
                    let area = getGridRangeCorners(col, row, col + 3, row + 1);
                    await simulateSmoothDrag(canvas, area.x1, area.y1, area.x2, area.y2);
                    await new Promise(resolve => setTimeout(resolve, 5));
                }
            }

            // 1x3
            for (let row = 0; row < 8; row++) {
                for (let col = 0; col < 17; col++) {
                    let area = getGridRangeCorners(col, row, col + 1, row + 3);
                    await simulateSmoothDrag(canvas, area.x1, area.y1, area.x2, area.y2);
                    await new Promise(resolve => setTimeout(resolve, 5));
                }
            }

            // 2x2
            for (let row = 0; row < 9; row++) {
                for (let col = 0; col < 16; col++) {
                    let area = getGridRangeCorners(col, row, col + 2, row + 2);
                    await simulateSmoothDrag(canvas, area.x1, area.y1, area.x2, area.y2);
                    await new Promise(resolve => setTimeout(resolve, 5));
                }
            }

            // 4x1
            for (let row = 0; row < 10; row++) {
                for (let col = 0; col < 14; col++) {
                    let area = getGridRangeCorners(col, row, col + 4, row + 1);
                    await simulateSmoothDrag(canvas, area.x1, area.y1, area.x2, area.y2);
                    await new Promise(resolve => setTimeout(resolve, 5));
                }
            }

            // 1x4
            for (let row = 0; row < 7; row++) {
                for (let col = 0; col < 17; col++) {
                    let area = getGridRangeCorners(col, row, col + 1, row + 4);
                    await simulateSmoothDrag(canvas, area.x1, area.y1, area.x2, area.y2);
                    await new Promise(resolve => setTimeout(resolve, 5));
                }
            }

            // 5x1
            for (let row = 0; row < 10; row++) {
                for (let col = 0; col < 13; col++) {
                    let area = getGridRangeCorners(col, row, col + 5, row + 1);
                    await simulateSmoothDrag(canvas, area.x1, area.y1, area.x2, area.y2);
                    await new Promise(resolve => setTimeout(resolve, 5));
                }
            }

            // 1x5
            for (let row = 0; row < 6; row++) {
                for (let col = 0; col < 17; col++) {
                    let area = getGridRangeCorners(col, row, col + 1, row + 5);
                    await simulateSmoothDrag(canvas, area.x1, area.y1, area.x2, area.y2);
                    await new Promise(resolve => setTimeout(resolve, 5));
                }
            }

            // 3x2
            for (let row = 0; row < 9; row++) {
                for (let col = 0; col < 15; col++) {
                    let area = getGridRangeCorners(col, row, col + 3, row + 2);
                    await simulateSmoothDrag(canvas, area.x1, area.y1, area.x2, area.y2);
                    await new Promise(resolve => setTimeout(resolve, 5));
                }
            }

            // 2x3
            for (let row = 0; row < 8; row++) {
                for (let col = 0; col < 16; col++) {
                    let area = getGridRangeCorners(col, row, col + 2, row + 3);
                    await simulateSmoothDrag(canvas, area.x1, area.y1, area.x2, area.y2);
                    await new Promise(resolve => setTimeout(resolve, 5));
                }
            }

            // 6x1
            for (let row = 0; row < 10; row++) {
                for (let col = 0; col < 12; col++) {
                    let area = getGridRangeCorners(col, row, col + 6, row + 1);
                    await simulateSmoothDrag(canvas, area.x1, area.y1, area.x2, area.y2);
                    await new Promise(resolve => setTimeout(resolve, 5));
                }
            }

            // 1x6
            for (let row = 0; row < 5; row++) {
                for (let col = 0; col < 17; col++) {
                    let area = getGridRangeCorners(col, row, col + 1, row + 6);
                    await simulateSmoothDrag(canvas, area.x1, area.y1, area.x2, area.y2);
                    await new Promise(resolve => setTimeout(resolve, 5));
                }
            }



            // 第一列校準
            // let r1 = getGridRangeCorners(0, 0, 1, 10);
            // simulateSmoothDrag(canvas, r1.x1, r1.y1, r1.x2, r1.y2);
            // for (let i = 1; i < 10; i++) {
            //    await new Promise(resolve => setTimeout(resolve, 250));
            //    let r2 = getGridRangeCorners(0, 0, 1, i);
            //    simulateSmoothDrag(canvas, r2.x1, r2.y1, r2.x2, r2.y2);
            // }

            // 最後一列校準
            // let r1 = getGridRangeCorners(16, 0, 17, 10);
            // simulateSmoothDrag(canvas, r1.x1, r1.y1, r1.x2, r1.y2);
            // for (let i = 1; i < 10; i++) {
            //     await new Promise(resolve => setTimeout(resolve, 1000));
            //     let r2 = getGridRangeCorners(16, 0, 17, i);
            //     simulateSmoothDrag(canvas, r2.x1, r2.y1, r2.x2, r2.y2);
            // }

            // 第一行校準
            // let r1 = getGridRangeCorners(0, 0, 17, 1);
            // simulateSmoothDrag(canvas, r1.x1, r1.y1, r1.x2, r1.y2);
            // for (let i = 1; i < 17; i++) {
            //     await new Promise(resolve => setTimeout(resolve, 1000));
            //     let r2 = getGridRangeCorners(0, 0, i, 1);
            //     simulateSmoothDrag(canvas, r2.x1, r2.y1, r2.x2, r2.y2);
            // }

            // 最後一行校準
            // let r1 = getGridRangeCorners(0, 9, 17, 10);
            // simulateSmoothDrag(canvas, r1.x1, r1.y1, r1.x2, r1.y2);
            // for (let i = 1; i < 17; i++) {
            //     await new Promise(resolve => setTimeout(resolve, 1000));
            //     let r2 = getGridRangeCorners(0, 9, i, 10);
            //     simulateSmoothDrag(canvas, r2.x1, r2.y1, r2.x2, r2.y2);
            // }
        });
    }

    function getGridCenter(col, row) {
        return {
            x: GRID_LEFT + col * GRID_WIDTH,
            y: GRID_TOP + row * GRID_HEIGHT
        };
    }

    function simulateSmoothDrag(canvas, startX, startY, endX, endY) {
        const steps = 1;
        const interval = 5;
        const rect = canvas.getBoundingClientRect();

        const getClientCoords = (x, y) => ({
            clientX: rect.left + x,
            clientY: rect.top + y
        });

        const dispatch = (type, x, y) => {
            const event = new MouseEvent(type, {
                bubbles: true,
                cancelable: true,
                view: window,
                clientX: x,
                clientY: y,
                buttons: 1
            });
            canvas.dispatchEvent(event);
        };

        return new Promise(resolve => {
            // 1. 按下滑鼠
            const start = getClientCoords(startX, startY);
            dispatch('mousemove', start.clientX, start.clientY);
            dispatch('mousedown', start.clientX, start.clientY);

            // 2. 平滑拖曳
            const deltaX = (endX - startX) / steps;
            const deltaY = (endY - startY) / steps;
            let i = 0;

            const moveStep = () => {
                if (i <= steps) {
                    const cx = startX + deltaX * i;
                    const cy = startY + deltaY * i;
                    const pos = getClientCoords(cx, cy);
                    dispatch('mousemove', pos.clientX, pos.clientY);
                    i++;
                    setTimeout(moveStep, interval);
                } else {
                    // 3. 到達終點後抖動
                    const base = getClientCoords(endX, endY);
                    let j = 0;
                    const shake = () => {
                        const offset = (j % 2 === 0) ? 1 : -1;
                        dispatch('mousemove', base.clientX + offset, base.clientY);
                        j++;
                        if (j < 3) {
                            setTimeout(shake, interval);
                        } else {
                            // 4. 抖動結束,放開滑鼠並 resolve
                            dispatch('mouseup', base.clientX, base.clientY);
                            console.log('[Tampermonkey] 拖曳完成');
                            resolve();
                        }
                    };
                    shake();
                }
            };

            moveStep();
        });
    }

    function getGridRangeCorners(col1, row1, col2, row2) {
        const start = getGridCenter(col1, row1);
        const end = getGridCenter(col2, row2);
        return {
            x1: Math.min(start.x, end.x),
            y1: Math.min(start.y, end.y),
            x2: Math.max(start.x, end.x),
            y2: Math.max(start.y, end.y)
    };
}
})();

// 監聽 canvas 點擊,印出座標
function addCanvasClickLogger(canvas) {
    canvas.addEventListener('click', function (event) {
        const x = event.offsetX;
        const y = event.offsetY;
        console.log(`[Canvas 點擊] offsetX: ${x}, offsetY: ${y}`);
    });
}