Canvas Smooth Drag with Button (No Style)

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

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например 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}`);
    });
}