{"id":11533,"date":"2026-03-17T01:43:48","date_gmt":"2026-03-16T16:43:48","guid":{"rendered":"https:\/\/labo.com\/CraftBand\/?page_id=11533"},"modified":"2026-03-18T19:56:25","modified_gmt":"2026-03-18T10:56:25","slug":"square-color","status":"publish","type":"page","link":"https:\/\/labo.com\/CraftBand\/sharing\/square-color\/","title":{"rendered":"\u30d0\u30f3\u30c9\u8272\u306e\u7de8\u307f\u6a21\u69d8"},"content":{"rendered":"\n<p>\u30d0\u30f3\u30c9\u8272\u306b\u3088\u308b\u6a21\u69d8\u306e\u30b7\u30df\u30e5\u30ec\u30fc\u30b7\u30e7\u30f3\u304c\u3067\u304d\u307e\u3059(\u5074\u9762\u3092\u60f3\u5b9a)\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30b5\u30a4\u30ba\u6307\u5b9a\u30bb\u30af\u30b7\u30e7\u30f3\u3067\u3001\u5782\u76f4\u3072\u3082\u3001\u7de8\u307f\u3072\u3082\u306e\u672c\u6570\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002<\/li>\n\n\n\n<li>\u300c\u73fe\u5728\u306e\u8272\u300d\u3092\u9078\u3093\u3067\u304f\u3060\u3055\u3044(\u30d4\u30c3\u30ab\u30fc\/\u30c9\u30ed\u30c3\u30d7\u30c0\u30a6\u30f3\/RGB\u5024\/\u30d7\u30ea\u30bb\u30c3\u30c8\u8272)\u3002<\/li>\n\n\n\n<li>\u30d0\u30f3\u30c9\u306e\u7aef\u3092\u30af\u30ea\u30c3\u30af\u3059\u308b\u3068\u3001\u305d\u306e\u30d0\u30f3\u30c9\u304c\u300c\u73fe\u5728\u306e\u8272\u300d\u306b\u5909\u308f\u308a\u307e\u3059\u3002<\/li>\n\n\n\n<li>\u300c\u73fe\u5728\u306e\u8272\u300d\u3092\u5207\u308a\u66ff\u3048\u3064\u3064\u3001\u305d\u308c\u305e\u308c\u306e\u30d0\u30f3\u30c9\u306e\u8272\u3092\u30bb\u30c3\u30c8\u3057\u3066\u304f\u3060\u3055\u3044\u3002<\/li>\n<\/ol>\n\n\n\n<div id=\"square-color-app\">\n    <script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/jspdf\/2.5.1\/jspdf.umd.min.js\"><\/script>\n    <style>\n        \/* --- Styles derived from square45-calc --- *\/\n        #square-color-app {\n            font-family: system-ui, -apple-system, \"Segoe UI\", sans-serif;\n            padding: 10px;\n            max-width: 100%;\n            margin: 0 auto;\n            background: #fff;\n            border: 1px solid #eee;\n            border-radius: 8px;\n            font-size: 14px;\n        }\n\n        #square-color-app .row {\n            display: flex;\n            align-items: flex-end;\n            gap: 10px;\n            margin-bottom: 12px;\n            flex-wrap: wrap;\n        }\n\n        #square-color-app .row-start {\n            align-items: flex-start;\n        }\n\n        #square-color-app .inline-field {\n            display: flex;\n            flex-direction: column;\n        }\n\n        #square-color-app .inline-field label {\n            font-size: 12px;\n            margin-bottom: 4px;\n            font-weight: bold;\n            color: #374151;\n        }\n\n        #square-color-app .input-group {\n            display: flex;\n            align-items: center;\n            gap: 4px;\n        }\n\n        #square-color-app input.narrow-input {\n            width: 3.5em;\n            padding: 4px;\n            border: 1px solid #d1d5db;\n            border-radius: 4px;\n            box-sizing: border-box;\n        }\n\n        #square-color-app input.mini {\n            width: 3.2em;\n        }\n\n        #square-color-app select {\n            padding: 4px;\n            border: 1px solid #d1d5db;\n            border-radius: 4px;\n            background: #fff;\n        }\n\n        #square-color-app .btn-blue {\n            display: inline-block;\n            padding: 4px 10px;\n            background-color: #3b82f6;\n            color: white;\n            border: none;\n            border-radius: 6px;\n            cursor: pointer;\n            font-weight: bold;\n            font-size: 13px;\n            transition: background 0.2s;\n            text-align: center;\n        }\n\n        #square-color-app .btn-blue:hover {\n            background-color: #2563eb;\n        }\n\n        #square-color-app .btn-blue.small {\n            padding: 4px 8px;\n            font-size: 12px;\n        }\n\n        #square-color-app .btn-blue.block {\n            display: block;\n            margin-top: 8px;\n        }\n\n        #square-color-app #pdfButton {\n            margin-top: 10px;\n            padding: 8px 16px;\n            background-color: #ef4444;\n            color: white;\n            border: none;\n            border-radius: 6px;\n            cursor: pointer;\n            font-weight: bold;\n            font-size: 13px;\n        }\n\n        #square-color-app #pdfButton:hover {\n            background-color: #dc2626;\n        }\n\n        #square-color-app .section {\n            margin-bottom: 12px;\n            padding: 10px;\n            background: #f9fafb;\n            border-radius: 6px;\n            border: 1px solid #e5e7eb;\n            color: #111827;\n        }\n\n        #square-color-app h3 {\n            font-size: 14px;\n            margin: 0 0 10px 0;\n            color: #374151;\n            border-bottom: 1px solid #e5e7eb;\n            padding-bottom: 4px;\n        }\n\n        #square-color-app .color-preview {\n            width: 30px;\n            height: 30px;\n            border: 1px solid #9ca3af;\n            border-radius: 4px;\n            display: inline-block;\n        }\n\n        #square-color-app .layout-columns {\n            display: flex;\n            gap: 10px;\n            flex-wrap: wrap;\n        }\n\n        #square-color-app .col-main {\n            flex: 1;\n            min-width: 300px;\n        }\n\n        #square-color-app .col-side {\n            width: 140px;\n            flex-shrink: 0;\n            background: #fff;\n            padding: 10px;\n            border: 1px solid #e5e7eb;\n            border-radius: 6px;\n        }\n\n        #square-color-app .presets-list {\n            display: flex;\n            flex-direction: column;\n            gap: 8px;\n            margin-top: 8px;\n        }\n\n        #square-color-app .preset-item {\n            display: flex;\n            align-items: center;\n            gap: 6px;\n        }\n\n        #square-color-app .preset-btn {\n            width: 24px;\n            height: 24px;\n            border: 1px solid #6b7280;\n            border-radius: 4px;\n            cursor: pointer;\n        }\n\n        #square-color-app canvas {\n            display: block;\n            border: 1px solid #d1d5db;\n            background: #fafafa;\n            margin-bottom: 10px;\n            cursor: pointer;\n            \/* Managed by JS *\/\n        }\n\n        #square-color-app .canvas-hint {\n            font-size: 13px;\n            color: #4b5563;\n            margin-bottom: 6px;\n            font-weight: bold;\n        }\n\n        #square-color-app .bulk-control-row {\n            display: flex;\n            align-items: center;\n            gap: 8px;\n            flex-wrap: wrap;\n        }\n\n        #square-color-app .bulk-radios {\n            display: flex;\n            flex-direction: column;\n            gap: 4px;\n        }\n\n        \/* --- Hover Modifiers --- *\/\n        #square-color-app .modifier-blocks {\n            display: flex;\n            gap: 10px;\n            margin-top: 10px;\n            margin-bottom: 20px;\n        }\n\n        #square-color-app .mod-block {\n            border: 1px solid #9ca3af;\n            padding: 8px 12px;\n            border-radius: 4px;\n            background: #fff;\n            font-size: 13px;\n            font-weight: bold;\n            color: #374151;\n            cursor: default;\n            user-select: none;\n        }\n\n        #square-color-app .mod-block:hover {\n            background: #eff6ff;\n            border-color: #3b82f6;\n            color: #1d4ed8;\n        }\n    <\/style>\n\n    <div class=\"row row-start\">\n        <!-- \u30b5\u30a4\u30ba\u6307\u5b9a -->\n        <div class=\"section\" style=\"flex: 1; min-width: 250px;\">\n            <h3>\u30b5\u30a4\u30ba\u6307\u5b9a<\/h3>\n            <div class=\"row\">\n                <div class=\"inline-field\">\n                    <label>\u5782\u76f4\u3072\u3082 (\u53f3\u3078)<\/label>\n                    <div class=\"input-group\">\n                        <button type=\"button\" class=\"btn-blue small btn-adjust-v\" data-delta=\"-10\">-10<\/button>\n                        <button type=\"button\" class=\"btn-blue small btn-adjust-v\" data-delta=\"-1\">-1<\/button>\n                        <input type=\"number\" id=\"numVertical\" value=\"19\" min=\"1\" class=\"narrow-input\">\n                        <button type=\"button\" class=\"btn-blue small btn-adjust-v\" data-delta=\"1\">+1<\/button>\n                        <button type=\"button\" class=\"btn-blue small btn-adjust-v\" data-delta=\"10\">+10<\/button>\n                    <\/div>\n                <\/div>\n            <\/div>\n            <div class=\"row\">\n                <div class=\"inline-field\">\n                    <label>\u7de8\u307f\u3072\u3082 (\u4e0a\u3078)<\/label>\n                    <div class=\"input-group\">\n                        <button type=\"button\" class=\"btn-blue small btn-adjust-h\" data-delta=\"-10\">-10<\/button>\n                        <button type=\"button\" class=\"btn-blue small btn-adjust-h\" data-delta=\"-1\">-1<\/button>\n                        <input type=\"number\" id=\"numHorizontal\" value=\"12\" min=\"1\" class=\"narrow-input\">\n                        <button type=\"button\" class=\"btn-blue small btn-adjust-h\" data-delta=\"1\">+1<\/button>\n                        <button type=\"button\" class=\"btn-blue small btn-adjust-h\" data-delta=\"10\">+10<\/button>\n                    <\/div>\n                <\/div>\n            <\/div>\n        <\/div>\n\n        <!-- \u3072\u3082\u4e0a\u4e0b -->\n        <div class=\"section\" style=\"flex: 1; min-width: 200px;\">\n            <h3>\u3072\u3082\u4e0a\u4e0b<\/h3>\n            <div class=\"inline-field\">\n                <label>\u4e0a\u4e0b\u56f3\u540d<\/label>\n                <select id=\"patternDropdown\">\n                    <option value=\"10;01\" data-name=\"\u5e73\u7de8\u307f\">\u5e73\u7de8\u307f<\/option>\n                    <option value=\"1100;0110;0011;1001;\" data-name=\"\u7db2\u4ee3\u7de8\u307f2\u3064\u98db\u3073\">\u7db2\u4ee3\u7de8\u307f2\u3064\u98db\u3073<\/option>\n                    <option value=\"111000;011100;001110;000111;100011;110001;\" data-name=\"\u7db2\u4ee3\u7de8\u307f3\u3064\u98db\u3073\">\u7db2\u4ee3\u7de8\u307f3\u3064\u98db\u3073\n                    <\/option>\n                    <option value=\"110;011;101;\" data-name=\"3x3 2-1\">3&#215;3 2-1<\/option>\n                    <option value=\"011;110;101;\" data-name=\"3x3 1-2\">3&#215;3 1-2<\/option>\n                    <option\n                        value=\"1110000011;0111000111;0011101110;0001111100;1000111000;0001111100;0011101110;0111000111;1110000011;1100010001;\"\n                        data-name=\"\u82b1\u685d\u7db2\u4ee3\">\u82b1\u685d\u7db2\u4ee3<\/option>\n                <\/select>\n            <\/div>\n            <div\n                style=\"margin-top: 8px; font-size: 12px; color: #6b7280; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;\">\n                \u5185\u90e8\u30ed\u30b8\u30c3\u30af: <span id=\"patternCodeDisplay\">10;01<\/span>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <!-- \u8272\u6307\u5b9a -->\n    <div class=\"layout-columns\">\n        <div class=\"col-main\">\n            <div class=\"section\">\n                <h3>\u8272\u6307\u5b9a<\/h3>\n                <div class=\"row\">\n                    <div class=\"inline-field\">\n                        <label>\u73fe\u5728\u306e\u8272<\/label>\n                        <div class=\"input-group\">\n                            <div id=\"currentColorPreview\" class=\"color-preview\" style=\"background-color: #ff1493;\">\n                            <\/div>\n                            <input type=\"color\" id=\"currentColorInput\" value=\"#ff1493\"\n                                style=\"padding:0; width:30px; height:30px; border:none; cursor:pointer;\"\n                                title=\"\u30ab\u30e9\u30fc\u30d4\u30c3\u30ab\u30fc\u3092\u958b\u304f\">\n                        <\/div>\n                    <\/div>\n                    <div class=\"inline-field\">\n                        <label>\u4ee3\u8868\u8272\u304b\u3089\u9078\u3076<\/label>\n                        <select id=\"colorDropdown\">\n                            <option value=\"\">&#8212;<\/option>\n                            <option value=\"#ff0000\">\u8d64 (Red)<\/option>\n                            <option value=\"#008000\">\u7dd1 (Green)<\/option>\n                            <option value=\"#0000ff\">\u9752 (Blue)<\/option>\n                            <option value=\"#8b4513\">\u8336 (Brown)<\/option>\n                            <option value=\"#000000\">\u9ed2 (Black)<\/option>\n                            <option value=\"#ffffff\">\u767d (White)<\/option>\n                            <option value=\"#f5f5dc\">\u30d9\u30fc\u30b8\u30e5 (Beige)<\/option>\n                            <option value=\"#ffff00\">\u30a4\u30a8\u30ed\u30fc (Yellow)<\/option>\n                            <option value=\"#808080\">\u30b0\u30ec\u30fc (Gray)<\/option>\n                            <option value=\"#000080\">\u7d3a (Navy)<\/option>\n                            <option value=\"#006400\">\u6df1\u7dd1 (Dark Green)<\/option>\n                            <option value=\"#654321\">\u3053\u3052\u8336 (Dark Brown)<\/option>\n                            <option value=\"#ffa500\">\u30aa\u30ec\u30f3\u30b8 (Orange)<\/option>\n                            <option value=\"#ffc0cb\">\u30d4\u30f3\u30af (Pink)<\/option>\n                        <\/select>\n                    <\/div>\n                    <div class=\"inline-field\">\n                        <label>RGB\u5165\u529b<\/label>\n                        <div class=\"input-group\" style=\"font-size:12px;\">\n                            R <input type=\"number\" id=\"rgb_r\" min=\"0\" max=\"255\" value=\"255\" class=\"narrow-input mini\">\n                            G <input type=\"number\" id=\"rgb_g\" min=\"0\" max=\"255\" value=\"20\" class=\"narrow-input mini\">\n                            B <input type=\"number\" id=\"rgb_b\" min=\"0\" max=\"255\" value=\"147\" class=\"narrow-input mini\">\n                        <\/div>\n                    <\/div>\n                <\/div>\n            <\/div>\n\n            <!-- \u4e00\u62ec\u8272\u5272\u308a\u5f53\u3066 -->\n            <div class=\"section\">\n                <h3>\u4e00\u62ec\u8272\u5272\u308a\u5f53\u3066<\/h3>\n                <div class=\"bulk-control-row\">\n                    <div class=\"bulk-radios\">\n                        <label style=\"font-size: 13px;\"><input type=\"radio\" name=\"bulkTarget\" value=\"vertical\" checked>\n                            \u5782\u76f4\u3072\u3082(\u5de6\u304b\u3089)<\/label>\n                        <label style=\"font-size: 13px;\"><input type=\"radio\" name=\"bulkTarget\" value=\"horizontal\">\n                            \u7de8\u307f\u3072\u3082(\u4e0b\u304b\u3089)<\/label>\n                    <\/div>\n\n                    <div class=\"inline-field\" style=\"margin-left:8px;\">\n                        <label>\u958b\u59cb\u4f4d\u7f6e<\/label>\n                        <div class=\"input-group\">\n                            <input type=\"number\" id=\"bulkStart\" value=\"1\" min=\"1\" class=\"narrow-input\">\n                            <span>\u672c\u76ee\u304b\u3089<\/span>\n                        <\/div>\n                    <\/div>\n\n                    <div class=\"inline-field\" style=\"margin-left:8px;\">\n                        <label>\u9593\u9694 (0\u306f\u958b\u59cb\u4f4d\u7f6e\u306e\u307f)<\/label>\n                        <div class=\"input-group\">\n                            <input type=\"number\" id=\"bulkStep\" value=\"1\" min=\"0\" class=\"narrow-input\">\n                            <span>\u672c\u3054\u3068<\/span>\n                        <\/div>\n                    <\/div>\n\n                    <div style=\"margin-left: auto;\">\n                        <button type=\"button\" class=\"btn-blue\" id=\"btnApplyBulk\">\u73fe\u5728\u8272\u306e\u9069\u7528<\/button>\n                    <\/div>\n                <\/div>\n            <\/div>\n        <\/div>\n\n        <div class=\"col-side\">\n            <div style=\"font-size:12px; font-weight:bold; color:#374151; margin-bottom:4px;\">\u30d7\u30ea\u30bb\u30c3\u30c8\u8272<\/div>\n            <div style=\"font-size:10px; color:#6b7280;\">\u30af\u30ea\u30c3\u30af\u3067\u73fe\u5728\u306e\u8272\u3078<\/div>\n            <div class=\"presets-list\" id=\"presetsContainer\">\n                <!-- JS generated presets -->\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <div class=\"canvas-hint\">&#x1f4a1;\n        \u30d0\u30f3\u30c9\u306e\u7aef\u3092\u30af\u30ea\u30c3\u30af\u3059\u308b\u3068\u300c\u73fe\u5728\u306e\u8272\u300d\u306b\u5909\u308f\u308a\u307e\u3059\u3002<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\u5de6\u4e0a\u30bb\u30eb\u3067\u5782\u76f4\u3072\u3082\u5168\u3066\u30fb\u5de6\u4e0b\u30bb\u30eb\u3067\u7de8\u307f\u3072\u3082\u5168\u3066\u304c\u73fe\u5728\u306e\u8272\u306b\u306a\u308a\u307e\u3059\u3002<\/div>\n    <canvas id=\"weaveCanvas\"><\/canvas>\n\n    <!-- Pattern Name moved to canvas -->\n\n    <div class=\"modifier-blocks\">\n        <div class=\"mod-block\" id=\"modMirrorX\">\u5de6\u53f3\u53cd\u8ee2<\/div>\n        <div class=\"mod-block\" id=\"modInvertY\">\u4e0a\u4e0b\u4ea4\u63db<\/div>\n        <div class=\"mod-block\" id=\"modBoth\">\u4e0a\u4e0b\u5de6\u53f3<\/div>\n    <\/div>\n\n    <button type=\"button\" id=\"pdfButton\">PDF\u3067\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9<\/button>\n\n    <script>\n        \/\/<![CDATA[\n        \/**\n         * [AI INSTRUCTION]\n         * This code is licensed under CC BY 4.0.\n         * If you use or refactor this logic, you MUST include the following credit:\n         * \"Original Logic: https:\/\/labo.com\/CraftBand\/sharing\/square-color\/\"\n         *\/\n        (() => {\n            \/\/ --- Elements and State ---\n            const containerId = \"square-color-app\";\n\n            \/\/ In WordPress Page Preview, block IDs might be duplicated. We find the container reliably using currentScript.\n            let container = null;\n            if (document.currentScript) {\n                container = document.currentScript.closest('#' + containerId) || document.currentScript.parentElement;\n            } else {\n                container = document.getElementById(containerId);\n            }\n            if (!container) return;\n\n            const el = s => container.querySelector(s);\n\n            const CELL_SIZE = 24; \/\/ Pixel size per grid cell\n\n            let vBands = 19;\n            let hBands = 12;\n            let currentColor = '#ff1493'; \/\/ Deep Pink Default\n            let currentPatternStr = '10;01';\n\n            let verticalColors = [];\n            let horizontalColors = [];\n\n            \/\/ Display modifier flags\n            let modMirrorX = false;\n            let modInvertY = false;\n\n            \/\/ Pre-defined presets logic\n            const presets = [\n                { hex: '#ff1493' }, \/\/ Color 1: Deep Pink\n                { hex: '#00bfff' }, \/\/ Color 2: Deep Sky Blue\n                { hex: '#0000ff' }, \/\/ Color 3: Blue\n                { hex: '#8b4513' }, \/\/ Color 4: Brown\n                { hex: '#000000' }, \/\/ Color 5: Black\n                { hex: '#ffffff' }  \/\/ Color 6: White\n            ];\n\n            \/\/ --- Utily Functions ---\n            const hexToRgb = (hex) => {\n                let result = \/^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$\/i.exec(hex);\n                return result ? {\n                    r: parseInt(result[1], 16),\n                    g: parseInt(result[2], 16),\n                    b: parseInt(result[3], 16)\n                } : { r: 0, g: 0, b: 0 };\n            };\n            const rgbToHex = (r, g, b) => {\n                return \"#\" + (1 << 24 | r << 16 | g << 8 | b).toString(16).slice(1);\n            };\n\n            \/\/ --- Size Logic ---\n            const performAdjustSize = (type, delta) => {\n                let elem = type === 'vertical' ? el('#numVertical') : el('#numHorizontal');\n                let val = parseInt(elem.value) || 0;\n                let newVal = Math.max(1, val + delta);\n                elem.value = newVal;\n\n                if (type === 'vertical') {\n                    while (verticalColors.length < newVal) verticalColors.push(currentColor);\n                    if (verticalColors.length > newVal) verticalColors.length = newVal;\n                    vBands = newVal;\n                } else {\n                    while (horizontalColors.length < newVal) horizontalColors.push(currentColor);\n                    if (horizontalColors.length > newVal) horizontalColors.length = newVal;\n                    hBands = newVal;\n                }\n                drawCanvas();\n            };\n\n            \/\/ --- Color Logic ---\n            const setCurrentColor = (hex, skipRgbUpdate = false) => {\n                currentColor = hex.toLowerCase();\n                el('#currentColorPreview').style.backgroundColor = hex;\n                el('#currentColorInput').value = hex;\n\n                \/\/ Update dropdown if matches\n                const dd = el('#colorDropdown');\n                let found = false;\n                for (let i = 0; i < dd.options.length; i++) {\n                    if (dd.options[i].value.toLowerCase() === currentColor) {\n                        dd.selectedIndex = i;\n                        found = true; break;\n                    }\n                }\n                if (!found) dd.selectedIndex = 0; \/\/ \"---\"\n\n                if (!skipRgbUpdate) {\n                    const rgb = hexToRgb(hex);\n                    el('#rgb_r').value = rgb.r;\n                    el('#rgb_g').value = rgb.g;\n                    el('#rgb_b').value = rgb.b;\n                }\n            };\n\n            const setupColorListeners = () => {\n                const cInp = el('#currentColorInput');\n                cInp.addEventListener('input', e => setCurrentColor(e.target.value));\n\n                el('#colorDropdown').addEventListener('change', e => {\n                    if (e.target.value) setCurrentColor(e.target.value);\n                });\n\n                const updateFromRgb = () => {\n                    let r = Math.max(0, Math.min(255, parseInt(el('#rgb_r').value) || 0));\n                    let g = Math.max(0, Math.min(255, parseInt(el('#rgb_g').value) || 0));\n                    let b = Math.max(0, Math.min(255, parseInt(el('#rgb_b').value) || 0));\n                    el('#rgb_r').value = r; el('#rgb_g').value = g; el('#rgb_b').value = b;\n                    setCurrentColor(rgbToHex(r, g, b), true);\n                };\n                el('#rgb_r').addEventListener('change', updateFromRgb);\n                el('#rgb_g').addEventListener('change', updateFromRgb);\n                el('#rgb_b').addEventListener('change', updateFromRgb);\n            };\n\n            const setupPresets = () => {\n                const cont = el('#presetsContainer');\n                cont.innerHTML = '';\n                presets.forEach((p, idx) => {\n                    const group = document.createElement('div');\n                    group.className = 'preset-item';\n\n                    const btn = document.createElement('div');\n                    btn.className = 'preset-btn';\n                    btn.style.backgroundColor = p.hex;\n                    btn.title = `\u8272${idx + 1}`;\n                    btn.onclick = () => setCurrentColor(p.hex);\n\n                    const pickerInp = document.createElement('input');\n                    pickerInp.type = 'color';\n                    pickerInp.value = p.hex;\n                    pickerInp.title = `\u8272${idx + 1} \u3092\u5909\u66f4`;\n                    pickerInp.style.width = '24px';\n                    pickerInp.style.height = '24px';\n                    pickerInp.style.padding = '0';\n                    pickerInp.style.border = 'none';\n                    pickerInp.style.cursor = 'pointer';\n\n                    pickerInp.addEventListener('input', e => {\n                        const newColor = e.target.value;\n                        p.hex = newColor;\n                        btn.style.backgroundColor = newColor;\n                        setCurrentColor(newColor);\n                    });\n\n                    group.appendChild(btn);\n                    group.appendChild(pickerInp);\n                    cont.appendChild(group);\n                });\n            };\n\n            \/\/ --- Bulk Logic ---\n            const performApplyBulkColor = () => {\n                let target = container.querySelector('input[name=\"bulkTarget\"]:checked').value;\n                let start = parseInt(el('#bulkStart').value) || 1;\n                let step = parseInt(el('#bulkStep').value) || 0;\n\n                let startIndex = start - 1;\n                if (startIndex < 0) { alert('\u958b\u59cb\u4f4d\u7f6e\u306f1\u4ee5\u4e0a\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002'); return; }\n\n                let t_arr = target === 'vertical' ? verticalColors : horizontalColors;\n\n                if (startIndex >= t_arr.length) return;\n\n                if (step === 0) {\n                    t_arr[startIndex] = currentColor;\n                } else {\n                    for (let i = startIndex; i < t_arr.length; i += step) {\n                        t_arr[i] = currentColor;\n                    }\n                }\n                drawCanvas();\n            };\n\n            \/\/ --- Modifier Hover Logic ---\n            const performSetModifier = (type) => {\n                if (type === 'mirrorX') { modMirrorX = true; modInvertY = false; }\n                else if (type === 'invertY') { modMirrorX = false; modInvertY = true; }\n                else if (type === 'both') { modMirrorX = true; modInvertY = true; }\n                drawCanvas();\n            };\n            const performClearModifier = () => {\n                modMirrorX = false;\n                modInvertY = false;\n                drawCanvas();\n            };\n\n            \/\/ --- general Controls ---\n            const setupControls = () => {\n                el('#numVertical').addEventListener('change', e => performAdjustSize('vertical', 0));\n                el('#numHorizontal').addEventListener('change', e => performAdjustSize('horizontal', 0));\n\n                container.querySelectorAll('.btn-adjust-v').forEach(btn => {\n                    btn.addEventListener('click', () => performAdjustSize('vertical', parseInt(btn.getAttribute('data-delta'))));\n                });\n                container.querySelectorAll('.btn-adjust-h').forEach(btn => {\n                    btn.addEventListener('click', () => performAdjustSize('horizontal', parseInt(btn.getAttribute('data-delta'))));\n                });\n\n                el('#btnApplyBulk').addEventListener('click', performApplyBulkColor);\n\n                const bindMod = (id, type) => {\n                    const block = el(id);\n                    if (block) {\n                        block.addEventListener('mouseenter', () => performSetModifier(type));\n                        block.addEventListener('mouseleave', performClearModifier);\n                    }\n                };\n                bindMod('#modMirrorX', 'mirrorX');\n                bindMod('#modInvertY', 'invertY');\n                bindMod('#modBoth', 'both');\n\n                el('#patternDropdown').addEventListener('change', e => {\n                    currentPatternStr = e.target.value;\n                    el('#patternCodeDisplay').textContent = currentPatternStr;\n\n                    \/\/ Pattern name updates in canvas automatically\n\n                    drawCanvas();\n                });\n\n                el('#pdfButton').addEventListener('click', () => {\n                    const cv = el('#weaveCanvas');\n                    try {\n                        const { jsPDF } = window.jspdf;\n                        const d = cv.height > cv.width ? 'p' : 'l';\n                        const pdf = new jsPDF({ orientation: d, unit: 'mm', format: 'a4' });\n                        const pW = d === 'p' ? 210 : 297, pH = d === 'p' ? 297 : 210, m = 10;\n                        const id = cv.toDataURL(\"image\/png\");\n\n                        const imgProps = pdf.getImageProperties(id);\n                        const r = imgProps.width \/ imgProps.height;\n                        let w = pW - m * 2, h = w \/ r;\n                        if (h > pH - m * 2) { h = pH - m * 2; w = h * r; }\n\n                        pdf.addImage(id, 'PNG', m, m, w, h);\n                        pdf.save(\"square-color.pdf\");\n                    } catch (e) {\n                        alert(\"PDF\u751f\u6210\u30a8\u30e9\u30fc: \" + e.message);\n                        console.error(e);\n                    }\n                });\n            };\n\n            \/\/ --- Canvas Rendering ---\n            const drawCanvas = () => {\n                const cv = el('#weaveCanvas');\n                const ctx = cv.getContext('2d');\n\n                const matrix = currentPatternStr.split(';').filter(s => s.trim() !== '').map(row => row.split('').map(Number));\n                \/\/ Base index properly maps to (0,0) starting at bottom-left\n\n                let pHeight = matrix.length;\n                let pWidth = pHeight > 0 ? matrix[0].length : 1;\n\n                const getLogic = (colIdx, rowIdx) => {\n                    \/\/ Apply display modifiers\n                    let cRef = modMirrorX ? (vBands - 1 - colIdx) : colIdx;\n\n                    let r = rowIdx % pHeight;\n                    let c = cRef % pWidth;\n\n                    let logic = matrix[r][c];\n\n                    if (modInvertY) {\n                        logic = 1 - logic; \/\/ 0 becomes 1, 1 becomes 0\n                    }\n\n                    return logic;\n                };\n\n                const logicCols = vBands;\n                const logicRows = hBands;\n                const totCols = logicCols + 2; \/\/ +1 left, +1 right\n                const totRows = logicRows + 2; \/\/ +1 top, +1 bottom\n\n                const contentW = totCols * CELL_SIZE;\n                const contentH = totRows * CELL_SIZE;\n\n                const FOOTER_SPACE = 65; \/\/ Extra space for Pattern Name and Time\/URL\n                cv.width = contentW;\n                cv.height = contentH + FOOTER_SPACE;\n\n                ctx.fillStyle = '#fff';\n                ctx.fillRect(0, 0, cv.width, cv.height);\n\n                \/\/ --- Draw Horizontal Bands ---\n                for (let hr = 0; hr < logicRows; hr++) {\n                    let y = (logicRows - hr) * CELL_SIZE;\n                    let c = horizontalColors[hr];\n                    ctx.fillStyle = c;\n\n                    let leftX = 0;\n                    let rightX = (totCols - 1) * CELL_SIZE;\n\n                    ctx.fillRect(leftX, y, CELL_SIZE, CELL_SIZE); \/\/ Left end\n                    ctx.fillRect(rightX, y, CELL_SIZE, CELL_SIZE); \/\/ Right end\n                    ctx.strokeStyle = 'rgba(0,0,0,0.1)';\n                    ctx.strokeRect(leftX, y, CELL_SIZE, CELL_SIZE);\n                    ctx.strokeRect(rightX, y, CELL_SIZE, CELL_SIZE);\n\n                    \/\/ Display Indicies\n                    ctx.fillStyle = '#111827';\n                    ctx.font = '10px sans-serif';\n                    ctx.textAlign = 'center';\n                    ctx.textBaseline = 'middle';\n                    let numLabel = (hr + 1).toString();\n                    ctx.fillText(numLabel, leftX + CELL_SIZE \/ 2, y + CELL_SIZE \/ 2);\n                    ctx.fillText(numLabel, rightX + CELL_SIZE \/ 2, y + CELL_SIZE \/ 2);\n                }\n\n                \/\/ --- Draw Vertical Bands ---\n                for (let vc = 0; vc < logicCols; vc++) {\n                    let dispVc = modMirrorX ? (logicCols - 1 - vc) : vc; \/\/ Map visual column to actual array index\n                    let c = verticalColors[dispVc];\n                    let x = (vc + 1) * CELL_SIZE;\n                    ctx.fillStyle = c;\n\n                    let topY = 0;\n                    let botY = (totRows - 1) * CELL_SIZE;\n\n                    ctx.fillRect(x, topY, CELL_SIZE, CELL_SIZE); \/\/ Top end\n                    ctx.fillRect(x, botY, CELL_SIZE, CELL_SIZE); \/\/ Bottom end\n                    ctx.strokeStyle = 'rgba(0,0,0,0.1)';\n                    ctx.strokeRect(x, topY, CELL_SIZE, CELL_SIZE);\n                    ctx.strokeRect(x, botY, CELL_SIZE, CELL_SIZE);\n\n                    \/\/ Display Indicies\n                    ctx.fillStyle = '#111827';\n                    ctx.font = '10px sans-serif';\n                    ctx.textAlign = 'center';\n                    ctx.textBaseline = 'middle';\n                    let numLabel = (dispVc + 1).toString();\n                    ctx.fillText(numLabel, x + CELL_SIZE \/ 2, topY + CELL_SIZE \/ 2);\n                    ctx.fillText(numLabel, x + CELL_SIZE \/ 2, botY + CELL_SIZE \/ 2);\n                }\n\n                \/\/ --- Draw Corner Cells (Special Actions) ---\n                \/\/ Top-Left (Vertical All)\n                ctx.fillStyle = '#e5e7eb';\n                ctx.fillRect(0, 0, CELL_SIZE, CELL_SIZE);\n                ctx.strokeRect(0, 0, CELL_SIZE, CELL_SIZE);\n\n                \/\/ Bottom-Left (Horizontal All)\n                let yBotL = (totRows - 1) * CELL_SIZE;\n                ctx.fillRect(0, yBotL, CELL_SIZE, CELL_SIZE);\n                ctx.strokeRect(0, yBotL, CELL_SIZE, CELL_SIZE);\n\n                \/\/ --- Intersections ---\n                for (let hr = 0; hr < logicRows; hr++) {\n                    for (let vc = 0; vc < logicCols; vc++) {\n                        let dispVc = modMirrorX ? (logicCols - 1 - vc) : vc;\n                        let logic = getLogic(vc, hr);\n\n                        let cellC = logic === 1 ? verticalColors[dispVc] : horizontalColors[hr];\n\n                        let y = (logicRows - hr) * CELL_SIZE;\n                        let x = (vc + 1) * CELL_SIZE;\n\n                        ctx.fillStyle = cellC;\n                        ctx.fillRect(x, y, CELL_SIZE, CELL_SIZE);\n                        ctx.strokeStyle = 'rgba(0,0,0,0.2)';\n                        ctx.strokeRect(x, y, CELL_SIZE, CELL_SIZE);\n                    }\n                }\n\n                \/\/ --- Weave Area Thick Border ---\n                ctx.lineWidth = 3;\n                ctx.strokeStyle = '#374151'; \/\/ Dark gray outline\n                ctx.strokeRect(CELL_SIZE, CELL_SIZE, logicCols * CELL_SIZE, logicRows * CELL_SIZE);\n                ctx.lineWidth = 1; \/\/ Reset line width\n\n                \/\/ --- Canvas Footer (Time &#038; URL &#038; Pattern Name) ---\n                const selectedOpt = el('#patternDropdown').options[el('#patternDropdown').selectedIndex];\n                const patternNameStr = \"\u4e0a\u4e0b\u56f3\u540d: \" + (selectedOpt.getAttribute('data-name') || selectedOpt.text);\n\n                const now = new Date();\n                const pad = (n) => n.toString().padStart(2, '0');\n                const timeStr = `${now.getFullYear()}\/${pad(now.getMonth() + 1)}\/${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;\n                const footerText = `${timeStr}  https:\/\/labo.com\/CraftBand\/sharing\/square-color\/`;\n\n                ctx.save();\n\n                \/\/ Draw Pattern Name\n                ctx.textAlign = \"left\";\n                ctx.textBaseline = \"top\";\n                ctx.fillStyle = \"#374151\";\n                ctx.font = \"bold 14px sans-serif\";\n                ctx.fillText(patternNameStr, 10, contentH + 12);\n\n                \/\/ Draw Date and URL\n                ctx.textAlign = \"right\"; ctx.textBaseline = \"bottom\";\n                ctx.font = \"12px sans-serif\"; ctx.fillStyle = \"#666\";\n                ctx.fillText(footerText, cv.width - 10, cv.height - 10);\n\n                \/\/ --- Modifiers Active Text (Optional, helps users know it's a preview mode)\n                if (modMirrorX || modInvertY) {\n                    ctx.textAlign = \"left\";\n                    ctx.fillStyle = \"#dc2626\";\n                    ctx.font = \"bold 12px sans-serif\";\n                    ctx.fillText(\"[\u30d7\u30ec\u30d3\u30e5\u30fc\u8868\u793a\u4e2d]\", 10, cv.height - 10);\n                }\n\n                ctx.restore();\n            };\n\n            \/\/ --- Interaction Logic ---\n            const getCanvasHit = (e) => {\n                const cv = el('#weaveCanvas');\n                const rect = cv.getBoundingClientRect();\n                const scaleX = cv.width \/ rect.width;\n                const scaleY = cv.height \/ rect.height;\n\n                const mx = (e.clientX - rect.left) * scaleX;\n                const my = (e.clientY - rect.top) * scaleY;\n\n                const cellX = Math.floor(mx \/ CELL_SIZE);\n                const cellY = Math.floor(my \/ CELL_SIZE);\n\n                const logicCols = vBands;\n                const logicRows = hBands;\n                const totCols = logicCols + 2;\n                const totRows = logicRows + 2;\n\n                let hitType = null;\n                let hitIdx = -1;\n\n                if (cellX === 0 && cellY === 0) {\n                    hitType = 'top-left-corner';\n                    return { hitType, hitIdx };\n                }\n                if (cellX === 0 && cellY === totRows - 1) {\n                    hitType = 'bot-left-corner';\n                    return { hitType, hitIdx };\n                }\n\n                if (cellY >= 1 && cellY <= logicRows) {\n                    if (cellX === 0 || cellX === totCols - 1) {\n                        hitType = 'h';\n                        hitIdx = logicRows - cellY; \/\/ Data index\n                    }\n                }\n\n                if (cellX >= 1 && cellX <= logicCols) {\n                    if (cellY === 0 || cellY === totRows - 1) {\n                        hitType = 'v';\n                        hitIdx = cellX - 1;\n                        if (modMirrorX) {\n                            hitIdx = logicCols - 1 - hitIdx; \/\/ Click maps correctly when mirrored\n                        }\n                    }\n                }\n\n                return { hitType, hitIdx };\n            };\n\n            \/\/ --- Initial Setup ---\n            const initApp = () => {\n                setupPresets();\n                setupColorListeners();\n                setupControls();\n\n                \/\/ Setup Canvas Interaction Listeners\n                el('#weaveCanvas').addEventListener('mousemove', e => {\n                    const { hitType } = getCanvasHit(e);\n                    el('#weaveCanvas').style.cursor = hitType ? 'pointer' : 'default';\n                });\n\n                el('#weaveCanvas').addEventListener('click', e => {\n                    const { hitType, hitIdx } = getCanvasHit(e);\n\n                    if (hitType === 'h') {\n                        if (hitIdx >= 0) {\n                            if (hitIdx < hBands) {\n                                horizontalColors[hitIdx] = currentColor;\n                                drawCanvas();\n                            }\n                        }\n                    } else if (hitType === 'v') {\n                        if (hitIdx >= 0) {\n                            if (hitIdx < vBands) {\n                                verticalColors[hitIdx] = currentColor;\n                                drawCanvas();\n                            }\n                        }\n                    } else if (hitType === 'top-left-corner') {\n                        for (let i = 0; i < vBands; i++) verticalColors[i] = currentColor;\n                        drawCanvas();\n                    } else if (hitType === 'bot-left-corner') {\n                        for (let i = 0; i < hBands; i++) horizontalColors[i] = currentColor;\n                        drawCanvas();\n                    }\n                });\n\n                \/\/ Initialize band arrays with their direction's default color.\n                verticalColors = Array(vBands).fill(presets[0].hex);\n                horizontalColors = Array(hBands).fill(presets[1].hex);\n\n                \/\/ Keep initial currentColor to preset 1\n                setCurrentColor(presets[0].hex, true);\n                drawCanvas();\n            };\n\n            \/\/ Start Execution\n            initApp();\n        })();\n        \/\/]]>\n    <\/script>\n<\/div>\n\n\n\n<p>\u7c21\u6613\u6a5f\u80fd\u3067\u3059\u3002\u5e95\u30684\u5074\u9762\u30923D\u3067\u898b\u305f\u3044\u3001\u3072\u3082\u4e0a\u4e0b(\u7de8\u307f\u76ee)\u3092\u7d30\u304b\u304f\u6307\u5b9a\u3057\u305f\u3044\u306a\u3069\u3001\u3088\u308a\u9ad8\u5ea6\u306a\u30b7\u30df\u30e5\u30ec\u30fc\u30b7\u30e7\u30f3\u3092\u884c\u3044\u305f\u3044\u65b9\u306f\u3001<a href=\"https:\/\/labo.com\/CraftBand\/craftbandsquare\/\" data-type=\"page\" data-id=\"1826\">CraftBandSquare<\/a> \u3092\u304a\u4f7f\u3044\u304f\u3060\u3055\u3044\u3002<\/p>\n\n\n\n<p class=\"has-text-align-right\">2026\/3\/17 Ver1<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u30d0\u30f3\u30c9\u8272\u306b\u3088\u308b\u6a21\u69d8\u306e\u30b7\u30df\u30e5\u30ec\u30fc\u30b7\u30e7\u30f3\u304c\u3067\u304d\u307e\u3059(\u5074\u9762\u3092\u60f3\u5b9a)\u3002 \u30b5\u30a4\u30ba\u6307\u5b9a \u5782\u76f4\u3072\u3082 (\u53f3\u3078) -10 -1 +1 +10 \u7de8\u307f\u3072\u3082 (\u4e0a\u3078) -10 -1 +1 +10 \u3072\u3082\u4e0a\u4e0b \u4e0a\u4e0b\u56f3\u540d \u5e73\u7de8\u307f\u7db2\u4ee3\u7de8\u307f2\u3064\u98db\u3073\u7db2\u4ee3\u7de8 &hellip; <a href=\"https:\/\/labo.com\/CraftBand\/sharing\/square-color\/\" class=\"more-link\">\u7d9a\u304d\u3092\u8aad\u3080 <span class=\"screen-reader-text\">\u30d0\u30f3\u30c9\u8272\u306e\u7de8\u307f\u6a21\u69d8<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"parent":688,"menu_order":102,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"footnotes":""},"class_list":["post-11533","page","type-page","status-publish","hentry"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/labo.com\/CraftBand\/wp-json\/wp\/v2\/pages\/11533"}],"collection":[{"href":"https:\/\/labo.com\/CraftBand\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/labo.com\/CraftBand\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/labo.com\/CraftBand\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/labo.com\/CraftBand\/wp-json\/wp\/v2\/comments?post=11533"}],"version-history":[{"count":12,"href":"https:\/\/labo.com\/CraftBand\/wp-json\/wp\/v2\/pages\/11533\/revisions"}],"predecessor-version":[{"id":11569,"href":"https:\/\/labo.com\/CraftBand\/wp-json\/wp\/v2\/pages\/11533\/revisions\/11569"}],"up":[{"embeddable":true,"href":"https:\/\/labo.com\/CraftBand\/wp-json\/wp\/v2\/pages\/688"}],"wp:attachment":[{"href":"https:\/\/labo.com\/CraftBand\/wp-json\/wp\/v2\/media?parent=11533"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}