Pomani Grid

flexible grid overlay on POSEMANIACS 30 seconds drawing

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Pomani Grid
// @name:ja      ぽまにぐりっど
// @namespace    https://malb7mm.github.io/
// @version      1.0.1
// @description  flexible grid overlay on POSEMANIACS 30 seconds drawing
// @description:ja  30秒ドローイング用の多機能グリッド
// @author       まるぶ
// @match        https://www.posemaniacs.com/tools/thirtyseconds
// @match        https://www.posemaniacs.com/*/tools/thirtyseconds
// @grant        none
// @license      CC0-1.0
// ==/UserScript==

(function() {
    'use strict';

    const config = {
        hcnt: 1,
        vcnt: 1,
        hoffset: 0,
        voffset: 0,
        color: "#eeeeee",
        enabled: true
    };
    const loadConfig = () => {
        const saved = localStorage.getItem("__userscript_pomanigrid__config");
        if (saved) {
            Object.assign(config, JSON.parse(saved));
        }
    };
    const saveConfig = () => {
        localStorage.setItem("__userscript_pomanigrid__config", JSON.stringify(config));
    };
    loadConfig();

    const init = () => {
        console.log("(ぽまにぐりっど初期化中……)");
        const eMain = document.querySelector("#__next > div > main");
        const eDivConfig = document.createElement("div");
        eMain.prepend(eDivConfig);

        eDivConfig.classList.add("px-md");
        eDivConfig.style.cssText = `
            background-color: #edd;
            display: flex;
            flex-direction: row;
            gap: 15px;
        `.trim();
        eDivConfig.innerHTML = `
            <p style="color: #800; font-weight: 600;">[グリッド]</p>
            <label>
                <input type="checkbox" ${config.enabled?'checked':''} id="__userscript_pomanigrid__enabled">
                表示
            </label>
            <label>
                <input type="number" min="1" id="__userscript_pomanigrid__hcnt" value="${config.hcnt}" style="width: 40px;">
                横分割数
            </label>
            <label>
                <input type="number" min="1" id="__userscript_pomanigrid__vcnt" value="${config.vcnt}" style="width: 40px;">
                縦分割数
            </label>
            <label>
                <input type="color" id="__userscript_pomanigrid__color" value="${config.color}" style="height: 0.8lh;">
                色
            </label>
            <label>
                <input type="range" min="-200" max="200" id="__userscript_pomanigrid__hoffset" value="${config.hoffset}" style="width: 100px;">
                横オフセット
            </label>
            <label>
                <input type="range" min="-200" max="200" id="__userscript_pomanigrid__voffset" value="${config.voffset}" style="width: 100px;">
                縦オフセット
            </label>
        `.trim();

        const eDivWrapper = document.createElement("div");
        eDivWrapper.style.cssText = "position: relative; display: inline-block;";
        const eCanvas = document.querySelector("#canvas > canvas");
        eCanvas.parentNode.insertBefore(eDivWrapper, eCanvas);
        eDivWrapper.appendChild(eCanvas);
        const eDivGrid = document.createElement("div");
        eDivWrapper.appendChild(eDivGrid);
        eDivGrid.style.cssText = `
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            pointerEvents: none;
        `.trim();

        const eInputEnabled = document.getElementById("__userscript_pomanigrid__enabled");
        const eInputHCnt = document.getElementById("__userscript_pomanigrid__hcnt");
        const eInputVCnt = document.getElementById("__userscript_pomanigrid__vcnt");
        const eInputHOffset = document.getElementById("__userscript_pomanigrid__hoffset");
        const eInputVOffset = document.getElementById("__userscript_pomanigrid__voffset");
        const eInputColor = document.getElementById("__userscript_pomanigrid__color");
        const updateGrid = () => {
            const enabled = eInputEnabled.checked;
            const hcnt = parseInt(eInputHCnt.value) || 1;
            const vcnt = parseInt(eInputVCnt.value) || 1;
            const hoffset = parseInt(eInputHOffset.value) || 0;
            const voffset = parseInt(eInputVOffset.value) || 0;
            const color = eInputColor.value;
            eDivGrid.style.opacity = enabled ? "0.5" : "0";
            eDivGrid.style.backgroundPosition = `${hoffset-1}px ${voffset-1}px`;
            eDivGrid.style.backgroundSize = "100% 100%";
            eDivGrid.style.backgroundImage = `
                repeating-linear-gradient(to bottom, ${color} 0, ${color} 1px, transparent 1px, transparent ${100/vcnt}%),
                repeating-linear-gradient(to right, ${color} 0, ${color} 1px, transparent 1px, transparent ${100/hcnt}%)
            `;
        };
        const updateConfig = () => {
            config.enabled = eInputEnabled.checked;
            config.hcnt = parseInt(eInputHCnt.value) || 1;
            config.vcnt = parseInt(eInputVCnt.value) || 1;
            config.hoffset = parseInt(eInputHOffset.value) || 0;
            config.voffset = parseInt(eInputVOffset.value) || 0;
            config.color = eInputColor.value;
            saveConfig();
            updateGrid();
        };
        eInputEnabled.addEventListener("change", updateConfig);
        eInputHCnt.addEventListener("input", updateConfig);
        eInputVCnt.addEventListener("input", updateConfig);
        eInputHOffset.addEventListener("input", updateConfig);
        eInputVOffset.addEventListener("input", updateConfig);
        eInputColor.addEventListener("input", updateConfig);
        updateGrid();
    };

    if (document.readyState === "complete") {
        init();
    } else {
        window.addEventListener("load", init);
    }
})();