{"id":12238,"date":"2026-05-05T10:41:19","date_gmt":"2026-05-05T01:41:19","guid":{"rendered":"https:\/\/labo.com\/CraftBand\/?page_id=12238"},"modified":"2026-05-05T11:33:49","modified_gmt":"2026-05-05T02:33:49","slug":"along-lines-calc","status":"publish","type":"page","link":"https:\/\/labo.com\/CraftBand\/sharing\/along-lines-calc\/","title":{"rendered":"\u7e26\u6a2a\u306e\u30b9\u30c6\u30c3\u30c1\u30fb2\u8272\u306e\u7d44\u5408\u305b\u6a21\u69d8"},"content":{"rendered":"\n<p><strong>A\u8272\u3068B \u8272\u3092\u30af\u30ea\u30c3\u30af\u3067\u5207\u308a\u66ff\u3048<\/strong>\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n\n\n\n<p><a href=\"https:\/\/labo.com\/CraftBand\/ppband\/level1-vh-variations\/\" data-type=\"post\" data-id=\"10802\" target=\"_blank\" rel=\"noreferrer noopener\">\u30ec\u30d9\u30eb1-\u7e26\u6a2a\u30b9\u30c6\u30c3\u30c1<\/a>\u306e\u6700\u5c0f\u5358\u4f4d\u304b\u3089\u4f5c\u3089\u308c\u308b\u69d8\u3005\u306a\u6a21\u69d8\u3092\u3001\u305d\u306e\u5834\u3067\u7c21\u5358\u306b\u898b\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u6587\u5b57\u306e\u4f4d\u7f6e\u306f\u30d0\u30f3\u30c9\u306e\u914d\u7f6e\u3092\u793a\u3057\u3066\u3044\u307e\u3059\u306e\u3067\u3001\u305d\u306e\u901a\u308a\u306b\u7de8\u3080\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u203b\u30b9\u30c6\u30c3\u30c1\u3084\u30ec\u30d9\u30eb\u306b\u3064\u3044\u3066\u306f\u3001<a href=\"https:\/\/labo.com\/CraftBand\/ppband\/plastics-stitch\/\" data-type=\"post\" data-id=\"10377\">\u3053\u3061\u3089\u306e\u30da\u30fc\u30b8<\/a>\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n\n\n\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/html2canvas\/1.4.1\/html2canvas.min.js\"><\/script>\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/jspdf\/2.5.1\/jspdf.umd.min.js\"><\/script>\n<style>\n    .along-lines-calc-wrapper {\n        font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;\n        max-width: 700px;\n        margin: 20px auto;\n    }\n\n    #along-lines-calc-app {\n        background: #ffffff;\n        color: #333;\n        border: 1px solid #ddd;\n        border-radius: 8px;\n        padding: 20px;\n        box-shadow: 0 4px 6px rgba(0,0,0,0.05);\n    }\n\n    #along-lines-calc-app h2 {\n        font-size: 1.2rem;\n        margin-top: 0;\n        border-bottom: 2px solid #87CEEB;\n        padding-bottom: 8px;\n        color: #444;\n    }\n\n    #along-lines-calc-app .control-section {\n        display: flex;\n        flex-direction: column;\n        gap: 15px;\n        margin-bottom: 20px;\n    }\n\n    #along-lines-calc-app .palette-row {\n        display: flex;\n        gap: 10px;\n        align-items: center;\n    }\n\n    #along-lines-calc-app .color-swatch {\n        width: 50px;\n        height: 50px;\n        border: 2px solid #ccc;\n        border-radius: 4px;\n        cursor: pointer;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n        font-weight: bold;\n        font-size: 1.2rem;\n        user-select: none;\n    }\n\n    #along-lines-calc-app .code-row {\n        display: flex;\n        gap: 5px;\n        align-items: flex-start;\n        flex-wrap: wrap;\n    }\n\n    #along-lines-calc-app .toggle-group {\n        display: flex;\n        flex-direction: column;\n        align-items: center;\n        gap: 5px;\n    }\n\n    #along-lines-calc-app .toggle-btn {\n        width: 40px;\n        height: 40px;\n        border: 1px solid #aaa;\n        border-radius: 4px;\n        cursor: pointer;\n        display: flex;\n        flex-direction: column;\n        align-items: center;\n        justify-content: center;\n        transition: all 0.2s;\n    }\n\n    #along-lines-calc-app .toggle-label {\n        font-size: 0.7rem;\n        font-weight: bold;\n        color: #666;\n    }\n\n    #along-lines-calc-app .toggle-val {\n        font-size: 1rem;\n        font-weight: bold;\n    }\n\n    #along-lines-calc-app .width-btn, #along-lines-calc-app .util-btn {\n        padding: 2px 4px;\n        font-size: 0.7rem;\n        background: #eee;\n        color: #333;\n        border: 1px solid #ccc;\n        border-radius: 3px;\n        cursor: pointer;\n        min-width: 30px;\n    }\n\n    #along-lines-calc-app .util-btn {\n        padding: 5px 10px;\n        font-weight: bold;\n        font-size: 0.8rem;\n    }\n\n    #along-lines-calc-app .canvas-container {\n        display: flex;\n        flex-direction: column;\n        align-items: center;\n        margin-top: 10px;\n    }\n\n    #along-lines-calc-app canvas {\n        max-width: 100%;\n        height: auto;\n        border: 1px solid #ccc;\n        box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n    }\n\n    #along-lines-calc-app .info-panel {\n        margin-top: 15px;\n        padding: 10px;\n        background: #f9f9f9;\n        border-radius: 4px;\n        font-size: 0.85rem;\n        line-height: 1.5;\n    }\n\n    #along-lines-calc-app .pattern-name-dropdown {\n        font-weight: bold;\n        color: #d81b60;\n        font-size: 1rem;\n        padding: 4px 8px;\n        border: 1px solid #ccc;\n        border-radius: 4px;\n        background-color: #fff;\n        cursor: pointer;\n        text-align: center;\n        max-width: 100%;\n        outline: none;\n    }\n    #along-lines-calc-app .pattern-name-dropdown.unnamed {\n        color: #999;\n        font-weight: normal;\n    }\n\n    .along-lines-calc-wrapper #btnPdfDownload {\n        margin-top: 10px;\n        padding: 10px 20px;\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    .along-lines-calc-wrapper #btnPdfDownload:hover {\n        background-color: #dc2626;\n    }\n<\/style>\n\n<div id=\"along-lines-calc-wrapper\" class=\"along-lines-calc-wrapper\">\n<div id=\"along-lines-calc-app\">\n    <h2>\u7e26\u6a2a\u30d9\u30fc\u30b9\u6a21\u69d8\u30b7\u30df\u30e5\u30ec\u30fc\u30bf\u30fc<\/h2>\n\n    <div class=\"control-section\">\n        <!-- Palette Select -->\n        <div class=\"palette-row\">\n            <div style=\"position: relative; width: 50px; height: 50px;\">\n                <div id=\"swatchA\" class=\"color-swatch\" style=\"background-color: #87CEEB; position: absolute; top: 0; left: 0; margin: 0; width: 100%; height: 100%; box-sizing: border-box;\">A<\/div>\n                <input type=\"color\" id=\"pickerA\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer;\">\n            <\/div>\n            <div style=\"position: relative; width: 50px; height: 50px;\">\n                <div id=\"swatchB\" class=\"color-swatch\" style=\"background-color: #ffffff; position: absolute; top: 0; left: 0; margin: 0; width: 100%; height: 100%; box-sizing: border-box;\">B<\/div>\n                <input type=\"color\" id=\"pickerB\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer;\">\n            <\/div>\n            <span style=\"font-size:0.8rem; color:#666\">\u2190 \u30af\u30ea\u30c3\u30af\u3067\u8272\u5909\u66f4<\/span>\n            <div style=\"margin-left: 10px; display: flex; gap: 5px;\">\n                <button id=\"btnSwapColors\" class=\"util-btn\">\u8272\u4ea4\u63db<\/button>\n                <button id=\"btnSwapABCode\" class=\"util-btn\">AB\u4ea4\u63db<\/button>\n            <\/div>\n        <\/div>\n\n        <div class=\"code-row\">\n            <!-- \u2460\u2461\u2462\u2463 (Base) -->\n            <div style=\"display:flex; flex-direction:column; align-items:center;\">\n                <div id=\"baseNameLabel\" style=\"font-size: 0.7rem; color: #666; margin-bottom: 2px;\"><\/div>\n                <div style=\"display:flex; gap:5px;\">\n                    <div class=\"toggle-group\"><span class=\"toggle-label\">\u2460<\/span><div class=\"toggle-btn\" data-type=\"base\" data-idx=\"0\"><span class=\"toggle-val\">A<\/span><\/div><\/div>\n                    <div class=\"toggle-group\"><span class=\"toggle-label\">\u2461<\/span><div class=\"toggle-btn\" data-type=\"base\" data-idx=\"1\"><span class=\"toggle-val\">B<\/span><\/div><\/div>\n                    <div class=\"toggle-group\"><span class=\"toggle-label\">\u2462<\/span><div class=\"toggle-btn\" data-type=\"base\" data-idx=\"2\"><span class=\"toggle-val\">A<\/span><\/div><\/div>\n                    <div class=\"toggle-group\"><span class=\"toggle-label\">\u2463<\/span><div class=\"toggle-btn\" data-type=\"base\" data-idx=\"3\"><span class=\"toggle-val\">B<\/span><\/div><\/div>\n                <\/div>\n                <div id=\"hoverL0Only\" class=\"util-btn\" style=\"margin-top:5px; width:100%; font-size:0.6rem; padding: 2px 0; background:#fff; border:1px solid #ddd; height:20px; display:flex; align-items:center; justify-content:center;\">\u30ec\u30d9\u30eb0\u306e\u307f<\/div>\n            <\/div>\n            \n            <div style=\"display:flex; flex-direction:column; align-items:center;\">\n                <div style=\"font-size: 0.7rem; margin-bottom: 2px;\">&nbsp;<\/div>\n                <div class=\"toggle-group\">\n                    <span class=\"toggle-label\" style=\"visibility:hidden;\">&#8211;<\/span>\n                    <span style=\"margin: 0 5px; height: 40px; display: flex; align-items: center; font-weight: bold; font-size: 1.2rem;\">&#8211;<\/span>\n                <\/div>\n            <\/div>\n\n            <!-- ab (L1) -->\n            <div style=\"display:flex; flex-direction:column; align-items:center;\">\n                <div style=\"font-size: 0.7rem; color: #666; margin-bottom: 2px;\">\u6c34\u5e73\u65b9\u5411<\/div>\n                <div style=\"display:flex; gap:5px;\">\n                    <div class=\"toggle-group\">\n                        <span class=\"toggle-label\">a<\/span><div class=\"toggle-btn\" data-type=\"l1\" data-idx=\"0\"><span class=\"toggle-val\">A<\/span><\/div>\n                    <\/div>\n                    <div class=\"toggle-group\">\n                        <span class=\"toggle-label\">b<\/span><div class=\"toggle-btn\" data-type=\"l1\" data-idx=\"1\"><span class=\"toggle-val\">A<\/span><\/div>\n                    <\/div>\n                <\/div>\n                <button class=\"width-btn\" data-type=\"l1\" style=\"margin-top:5px; width:100%; height:20px; padding:0;\">1\/2<\/button>\n            <\/div>\n\n            <!-- cd (L2) -->\n            <div style=\"display:flex; flex-direction:column; align-items:center; margin-left: 5px;\">\n                <div style=\"font-size: 0.7rem; color: #666; margin-bottom: 2px;\">\u5782\u76f4\u65b9\u5411<\/div>\n                <div style=\"display:flex; gap:5px;\">\n                    <div class=\"toggle-group\">\n                        <span class=\"toggle-label\">c<\/span><div class=\"toggle-btn\" data-type=\"l2\" data-idx=\"0\"><span class=\"toggle-val\">A<\/span><\/div>\n                    <\/div>\n                    <div class=\"toggle-group\">\n                        <span class=\"toggle-label\">d<\/span><div class=\"toggle-btn\" data-type=\"l2\" data-idx=\"1\"><span class=\"toggle-val\">A<\/span><\/div>\n                    <\/div>\n                <\/div>\n                <button class=\"width-btn\" data-type=\"l2\" style=\"margin-top:5px; width:100%; height:20px; padding:0;\">1\/2<\/button>\n            <\/div>\n\n            <!-- \u8ee2\u7f6e -->\n            <div style=\"display:flex; flex-direction:column; align-items:flex-start; margin-left: 15px;\">\n                <div style=\"font-size: 0.7rem; margin-bottom: 2px;\">&nbsp;<\/div>\n                <div class=\"toggle-group\">\n                    <span class=\"toggle-label\" style=\"visibility:hidden;\">&#8211;<\/span>\n                    <button id=\"btnTranspose\" class=\"util-btn\" style=\"height: 40px; padding: 0 15px; font-weight: bold; background: #e8f5e9; border-color: #a5d6a7; margin: 0;\">\u8ee2\u7f6e(90\u5ea6\u56de\u8ee2)<\/button>\n                <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <div class=\"canvas-container\">\n        <div id=\"patternDisplayHeader\" style=\"margin-bottom: 5px; text-align: center; height: 55px; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 5px;\">\n            <select id=\"patternNameSelect\" class=\"pattern-name-dropdown\"><\/select>\n            <div id=\"currentCodeTag\" style=\"font-size: 0.9rem; color: #444;\"><\/div>\n        <\/div>\n        <canvas id=\"patternCanvas\"><\/canvas>\n    <\/div>\n\n    <div class=\"info-panel\" id=\"equivPanel\" style=\"margin-top: 15px; padding: 10px; background: #f9f9f9; border-radius: 4px; font-size: 0.82rem; line-height: 1.4;\">\n        <div id=\"equivCodes\" style=\"word-break: break-all;\"><\/div>\n    <\/div>\n\n    <div style=\"display:flex; justify-content:center; gap: 10px; margin-top: 15px;\">\n        <button id=\"btnCraftBandOut\" class=\"util-btn\" style=\"padding: 8px 15px; background: #e3f2fd; border-color: #90caf9;\">CraftBandSquare\u3078\u306e\u8a2d\u5b9a<\/button>\n    <\/div>\n    <div id=\"craftBandSquarePanel\" class=\"info-panel\" style=\"display:none; border: 1px solid #90caf9; margin-top: 10px; overflow-x: auto;\"><\/div>\n<\/div>\n\n<div style=\"text-align:center; margin-top:20px; margin-bottom: 20px;\">\n    <button id=\"btnPdfDownload\">PDF\u3067\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9<\/button>\n<\/div>\n<\/div>\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\/along-lines-calc\/\"\n *\/\n(() => {\n    const containerId = \"along-lines-calc-wrapper\";\n    let container = null;\n    if (document.currentScript) {\n        container = document.currentScript.closest('#' + containerId);\n        if (!container) container = document.currentScript.parentElement;\n    } else {\n        container = document.getElementById(containerId);\n    }\n    if (!container) return;\n\n    const el = s => container.querySelector(s);\n    const els = s => container.querySelectorAll(s);\n\n    \/\/ --- State ---\n    const state = {\n        colorA: '#87CEEB',\n        colorB: '#ffffff',\n        code: {\n            base: ['A', 'B', 'A', 'B'],\n            l1: ['A', 'A'],\n            l2: ['A', 'A']\n        },\n        widths: {\n            l1: 0.5,\n            l2: 0.5\n        },\n        isPreviewL0: false\n    };\n\n    const PATTERNS_DB = [\n        { jp: \"\u4e95\u6841(\u3044\u3052\u305f)\", en: \"Grid\", codes: [\"AAAA-BBBB\"] },\n        { jp: \"\u6881(\u306f\u308a)\", en: \"Beams\", codes: [\"BBAA-AABB\"] },\n        { jp: \"\u7a93(\u307e\u3069)\", en: \"Windowpane\", codes: [\"ABAB-AAAA\"] },\n        { jp: \"\u9023\u7a93(\u308c\u3093\u307e\u3069)\", en: \"Linked Window\", codes: [\"BBAB-AAAA\"] }\n    ];\n\n    \/\/ --- Logic ---\n    const getFullCodeString = obj => {\n        if (!obj) return \"\";\n        if (!obj.base) return \"\";\n        if (!obj.l1) return \"\";\n        if (!obj.l2) return \"\";\n        return `${obj.base.join('')}-${obj.l1.join('')}${obj.l2.join('')}`;\n    };\n\n    const findMatches = () => {\n        const curCode = state.code;\n        const curCodeStr = getFullCodeString(curCode);\n\n        const permute = (codeObj, p, invert) => {\n            const swap = v => (v === null ? null : (invert ? (v === 'A' ? 'B' : 'A') : v));\n            const base = [\n                swap(codeObj.base[p[0]]), swap(codeObj.base[p[1]]), \n                swap(codeObj.base[p[2]]), swap(codeObj.base[p[3]])\n            ];\n            const oldOverlays = [\n                codeObj.l1[0], codeObj.l1[1], \n                codeObj.l2[0], codeObj.l2[1]\n            ];\n            const overlays = [\n                swap(oldOverlays[p[0]]), swap(oldOverlays[p[1]]), \n                swap(oldOverlays[p[2]]), swap(oldOverlays[p[3]])\n            ];\n            return {\n                base,\n                l1: [overlays[0], overlays[1]],\n                l2: [overlays[2], overlays[3]]\n            };\n        };\n\n        const pOriginal = [0, 1, 2, 3];\n        const pShift    = [1, 0, 3, 2];\n        const pTrans1   = [3, 2, 0, 1];\n        const pTrans2   = [2, 3, 1, 0];\n\n        const shiftCodes = new Set();\n        const invCodes = new Set();\n        const transCodes = new Set();\n        const transInvCodes = new Set();\n\n        const add = (p, invert, set) => {\n            const code = getFullCodeString(permute(curCode, p, invert));\n            if (code) set.add(code);\n        };\n\n        add(pOriginal, false, shiftCodes);\n        add(pShift, false, shiftCodes);\n        \n        add(pOriginal, true, invCodes);\n        add(pShift, true, invCodes);\n\n        add(pTrans1, false, transCodes);\n        add(pTrans2, false, transCodes);\n\n        add(pTrans1, true, transInvCodes);\n        add(pTrans2, true, transInvCodes);\n\n        return { \n            shiftCodes: [...shiftCodes].sort(), \n            invCodes: [...invCodes].sort(),\n            transCodes: [...transCodes].sort(),\n            transInvCodes: [...transInvCodes].sort()\n        };\n    };\n\n    const draw = () => {\n        const canvas = el('#patternCanvas'), ctx = canvas.getContext('2d'), SIZE = 40, VW = 12, VH = 8;\n        canvas.width = SIZE * VW; canvas.height = SIZE * VH + 50;\n        ctx.fillStyle = '#fff'; ctx.fillRect(0, 0, canvas.width, canvas.height);\n        const colors = { A: state.colorA, B: state.colorB };\n        ctx.save(); ctx.beginPath(); ctx.rect(0, 0, canvas.width, SIZE * VH); ctx.clip();\n        for (let y = 0; y !== VH; y++) {\n            for (let x = 0; x !== VW; x++) {\n                const isVTop = ((x + y) % 2 === 0);\n                \/\/ Draw the underlying base band\n                ctx.fillStyle = isVTop ? colors[state.code.base[(x % 2) + 2]] : colors[state.code.base[y % 2]];\n                ctx.fillRect(x * SIZE, (VH - 1 - y) * SIZE, SIZE, SIZE);\n                ctx.strokeStyle = 'rgba(0,0,0,0.1)'; ctx.strokeRect(x * SIZE, (VH - 1 - y) * SIZE, SIZE, SIZE);\n\n                if (!state.isPreviewL0) {\n                    const w1 = SIZE * state.widths.l1;\n                    const w2 = SIZE * state.widths.l2;\n\n                    if (!isVTop) {\n                        if (w1 !== 0) {\n                            ctx.fillStyle = colors[state.code.l1[y % 2]];\n                            ctx.fillRect(x * SIZE, (VH - 1 - y) * SIZE + (SIZE - w1)\/2, SIZE, w1);\n                        }\n                    }\n                    if (isVTop) {\n                        if (w2 !== 0) {\n                            ctx.fillStyle = colors[state.code.l2[x % 2]];\n                            ctx.fillRect(x * SIZE + (SIZE - w2)\/2, (VH - 1 - y) * SIZE, w2, SIZE);\n                        }\n                    }\n                }\n            }\n        }\n        ctx.restore();\n\n        ctx.fillStyle = '#999'; ctx.font = '10px sans-serif'; ctx.textAlign = 'right';\n        const now = new Date(); const timeStr = `${now.getFullYear()}\/${(now.getMonth()+1).toString().padStart(2,'0')}\/${now.getDate().toString().padStart(2,'0')} ${now.getHours().toString().padStart(2,'0')}:${now.getMinutes().toString().padStart(2,'0')}`;\n        ctx.fillText(timeStr, canvas.width - 5, canvas.height - 20); ctx.fillText('https:\/\/labo.com\/CraftBand\/sharing\/along-lines-calc\/', canvas.width - 5, canvas.height - 5);\n        const { shiftCodes, invCodes, transCodes, transInvCodes } = findMatches();\n        const curCodeStr = getFullCodeString(state.code);\n        \n        const shiftSet = new Set(shiftCodes);\n        const invSet = new Set(invCodes);\n        const transSet = new Set(transCodes);\n        const transInvSet = new Set(transInvCodes);\n        let nameIndex = 'unnamed';\n        \n        for (let i = 0; i !== PATTERNS_DB.length; i++) {\n            const p = PATTERNS_DB[i];\n            for (const code of p.codes) {\n                let matched = false;\n                if (code === curCodeStr) matched = true;\n                if (shiftSet.has(code)) matched = true;\n                if (invSet.has(code)) matched = true;\n                if (transSet.has(code)) matched = true;\n                if (transInvSet.has(code)) matched = true;\n                if (matched) {\n                    nameIndex = i;\n                    break;\n                }\n            }\n            if (nameIndex !== 'unnamed') break;\n        }\n\n        const selectEl = el('#patternNameSelect');\n        selectEl.value = nameIndex;\n        if (nameIndex === 'unnamed') {\n            selectEl.classList.add('unnamed');\n        } else {\n            selectEl.classList.remove('unnamed');\n        }\n        \n        el('#currentCodeTag').textContent = `Code: ${curCodeStr}`;\n        \n        const formatCode = (tCodeStr, sCodeStr) => {\n            if (tCodeStr === sCodeStr) return `<b>${tCodeStr}<\/b>`;\n            const t = tCodeStr.split('-'), s = sCodeStr.split('-');\n            if (t[0] === s[0]) {\n                if (t[1] === s[1]) return `<b>${t[0]}-${t[1]}<\/b>`;\n                return `<b>${t[0]}<\/b>-${t[1]}`;\n            }\n            return tCodeStr;\n        };\n\n        const shiftArr = [...shiftCodes];\n        const invArr = invCodes.filter(c => !shiftSet.has(c));\n        const transArr = transCodes.filter(c => !shiftSet.has(c) && !invSet.has(c));\n        const transInvArr = transInvCodes.filter(c => !shiftSet.has(c) && !invSet.has(c) && !transSet.has(c));\n\n        let html = \"\"; \n        const wrap = (label, list) => {\n            if (list.length !== 0) return `<div style=\"margin-bottom: 5px;\"><strong>${label}<\/strong><br>${list.map(c => formatCode(c, curCodeStr)).join(', ')}<\/div>`;\n            return \"\";\n        };\n        html += wrap(\"\u540c\u4e00\u6a21\u69d8(\u30b7\u30d5\u30c8):\", shiftArr); \n        html += wrap(\"\u540c\u4e00\u6a21\u69d8(\u8272\u53cd\u8ee2):\", invArr);\n        html += wrap(\"\u540c\u4e00\u6a21\u69d8(\u8ee2\u7f6e):\", transArr);\n        html += wrap(\"\u540c\u4e00\u6a21\u69d8(\u8ee2\u7f6e\u30fb\u8272\u53cd\u8ee2):\", transInvArr);\n        el('#equivCodes').innerHTML = html; \n\n        if (html !== \"\") el('#equivPanel').style.display = \"block\";\n        else el('#equivPanel').style.display = \"none\";\n    };\n\n    const updateToggles = () => {\n        const getBaseName = (bArr) => {\n            const b = bArr.join('');\n            if (['AAAA', 'BBBB'].indexOf(b) !== -1) return '\u5358\u8272\u30d9\u30fc\u30b9';\n            if (['BBAA', 'AABB'].indexOf(b) !== -1) return '\u683c\u5b50\u30d9\u30fc\u30b9';\n            if (['ABAB', 'BABA'].indexOf(b) !== -1) return '\u6a2a\u30b9\u30c8\u30e9\u30a4\u30d7\u30d9\u30fc\u30b9';\n            if (['BAAB', 'ABBA'].indexOf(b) !== -1) return '\u7e26\u30b9\u30c8\u30e9\u30a4\u30d7\u30d9\u30fc\u30b9';\n            if (['BAAA', 'ABBB'].indexOf(b) !== -1) return '\u30ae\u30f3\u30ac\u30e0X1\u30d9\u30fc\u30b9';\n            if (['ABAA', 'BABB'].indexOf(b) !== -1) return '\u30ae\u30f3\u30ac\u30e0X2\u30d9\u30fc\u30b9';\n            if (['AABA', 'BBAB'].indexOf(b) !== -1) return '\u30ae\u30f3\u30ac\u30e0X3\u30d9\u30fc\u30b9';\n            if (['AAAB', 'BBBA'].indexOf(b) !== -1) return '\u30ae\u30f3\u30ac\u30e0X4\u30d9\u30fc\u30b9';\n            return '';\n        };\n        el('#baseNameLabel').textContent = getBaseName(state.code.base);\n        el('#swatchA').style.backgroundColor = state.colorA; el('#swatchB').style.backgroundColor = state.colorB;\n        if (el('#craftBandSquarePanel')) el('#craftBandSquarePanel').style.display = 'none';\n        els('.toggle-btn').forEach(btn => {\n            const type = btn.getAttribute('data-type'), idx = parseInt(btn.getAttribute('data-idx')), valSpan = btn.querySelector('.toggle-val');\n            let val = state.code[type][idx];\n            valSpan.textContent = val;\n            if (val === 'A') btn.style.background = state.colorA;\n            else if (val === 'B') btn.style.background = state.colorB;\n            else btn.style.background = '#eee';\n        });\n\n        els('.width-btn').forEach(btn => {\n            const type = btn.getAttribute('data-type');\n            if (type) {\n                if (state.widths[type] !== undefined) {\n                    btn.textContent = state.widths[type] === 0.333 ? '1\/3' : (state.widths[type] === 0.5 ? '1\/2' : (state.widths[type] === 0.25 ? '1\/4' : '0 (\u975e\u8868\u793a)'));\n                }\n            }\n        });\n    };\n\n    const toggleChar = c => c === 'A' ? 'B' : 'A';\n    els('.toggle-btn').forEach(btn => {\n        btn.onclick = () => {\n            const type = btn.getAttribute('data-type'), idx = parseInt(btn.getAttribute('data-idx'));\n            state.code[type][idx] = toggleChar(state.code[type][idx]);\n            updateToggles(); draw();\n        };\n    });\n\n    el('#hoverL0Only').onmouseenter = () => { state.isPreviewL0 = true; draw(); };\n    el('#hoverL0Only').onmouseleave = () => { state.isPreviewL0 = false; draw(); };\n\n    el('#btnSwapColors').onclick = () => { \n        const oldA = state.colorA;\n        state.colorA = state.colorB;\n        state.colorB = oldA;\n        updateToggles(); draw(); \n    };\n    el('#btnSwapABCode').onclick = () => {\n        state.code.base = state.code.base.map(toggleChar);\n        state.code.l1 = state.code.l1.map(toggleChar);\n        state.code.l2 = state.code.l2.map(toggleChar);\n        updateToggles(); draw();\n    };\n\n    el('#btnTranspose').onclick = () => {\n        const oldBase = state.code.base;\n        const oldL1 = state.code.l1;\n        const oldL2 = state.code.l2;\n        \n        state.code.base = [oldBase[3], oldBase[2], oldBase[0], oldBase[1]];\n        state.code.l1 = [oldL2[1], oldL2[0]];\n        state.code.l2 = [oldL1[0], oldL1[1]];\n        \n        const oldW1 = state.widths.l1;\n        state.widths.l1 = state.widths.l2;\n        state.widths.l2 = oldW1;\n\n        updateToggles(); draw();\n    };\n\n    els('.width-btn[data-type]').forEach(btn => {\n        btn.onclick = () => {\n            const type = btn.getAttribute('data-type'), cur = state.widths[type];\n            if (cur === 0.5) state.widths[type] = 0.333;\n            else if (cur === 0.333) state.widths[type] = 0.25;\n            else if (cur === 0.25) state.widths[type] = 0;\n            else state.widths[type] = 0.5;\n            \n            updateToggles(); draw();\n        };\n    });\n\n    el('#pickerA').oninput = e => { state.colorA = e.target.value; updateToggles(); draw(); };\n    el('#pickerB').oninput = e => { state.colorB = e.target.value; updateToggles(); draw(); };\n\n    \/\/ Initialize dropdown\n    const nameSelect = el('#patternNameSelect');\n    PATTERNS_DB.forEach((p, i) => {\n        const opt = document.createElement('option');\n        opt.value = i;\n        opt.textContent = `${p.jp}\u6a21\u69d8 \/ ${p.en} Pattern`;\n        nameSelect.appendChild(opt);\n    });\n    \n    const unnamedOpt = document.createElement('option');\n    unnamedOpt.value = 'unnamed';\n    unnamedOpt.textContent = '<\u540d\u524d\u52df\u96c6\u4e2d> \/ Unnamed';\n    unnamedOpt.disabled = true;\n    nameSelect.appendChild(unnamedOpt);\n\n    nameSelect.addEventListener('change', (e) => {\n        const val = e.target.value;\n        if (val === 'unnamed') return;\n        \n        const targetCodeStr = PATTERNS_DB[val].codes[0];\n        const parts = targetCodeStr.split('-');\n        if (parts.length === 2) {\n            state.code.base = parts[0].split('');\n            state.code.l1 = [parts[1][0], parts[1][1]];\n            state.code.l2 = [parts[1][2], parts[1][3]];\n            updateToggles();\n            draw();\n        }\n    });\n\n    \/\/ --- CraftBandSquare Output ---\n    const generateCraftBandOutput = () => {\n        const c = state.code;\n        const colors = { A: 'A\u8272', B: 'B\u8272' };\n        \n        const b12 = c.base[0] + c.base[1];\n        let txt12 = \"\";\n        if (b12 === 'AA') txt12 = \"\u5168\u3066A\u8272\";\n        else if (b12 === 'BB') txt12 = \"\u5168\u3066B\u8272\";\n        else if (b12 === 'AB') txt12 = \"\u3072\u3082\u756a\u53f7\u9806\u306b(\u4e0b\u304b\u3089\u4e0a\u306b) A,B,A,B...\";\n        else if (b12 === 'BA') txt12 = \"\u3072\u3082\u756a\u53f7\u9806\u306b(\u4e0b\u304b\u3089\u4e0a\u306b) B,A,B,A...\";\n        \n        const b34 = c.base[2] + c.base[3];\n        let txt34 = \"\";\n        if (b34 === 'AA') txt34 = \"\u5168\u3066A\u8272\";\n        else if (b34 === 'BB') txt34 = \"\u5168\u3066B\u8272\";\n        else if (b34 === 'AB') txt34 = \"\u3072\u3082\u756a\u53f7\u9806\u306b(\u5de6\u304b\u3089\u53f3\u306b) A,B,A,B...\";\n        else if (b34 === 'BA') txt34 = \"\u3072\u3082\u756a\u53f7\u9806\u306b(\u5de6\u304b\u3089\u53f3\u306b) B,A,B,A...\";\n        \n        const wBtn1 = el('.width-btn[data-type=\"l1\"]').textContent;\n        const wBtn2 = el('.width-btn[data-type=\"l2\"]').textContent;\n\n        const records = [];\n        let seq = 1;\n        const addRec = (face, angle, center, w, color, start, step, pos, memo) => {\n            records.push(`<tr><td style=\"border: 1px solid #ccc; padding: 4px;\">${seq++}<\/td><td style=\"border: 1px solid #ccc; padding: 4px;\">${face}<\/td><td style=\"border: 1px solid #ccc; padding: 4px;\">${angle}<\/td><td style=\"border: 1px solid #ccc; padding: 4px;\">${center}<\/td><td style=\"border: 1px solid #ccc; padding: 4px;\">${w}<\/td><td style=\"border: 1px solid #ccc; padding: 4px;\">${color}<\/td><td style=\"border: 1px solid #ccc; padding: 4px;\">${start}<\/td><td style=\"border: 1px solid #ccc; padding: 4px;\">${step}<\/td><td style=\"border: 1px solid #ccc; padding: 4px;\">${pos}<\/td><td style=\"border: 1px solid #ccc; padding: 4px;\">${memo}<\/td><\/tr>`);\n        };\n\n        const l1str = c.l1.join('');\n        if (l1str === 'AA') {\n            addRec('\u5074\u9762', '0\u5ea6(\u6c34\u5e73\u30fb\u6a2a)', '\u3072\u3082\u4e2d\u592e', wBtn1, colors['A'], 1, 1, '\u3068\u3082\u7de8\u307f', 'ab');\n        } else if (l1str === 'BB') {\n            addRec('\u5074\u9762', '0\u5ea6(\u6c34\u5e73\u30fb\u6a2a)', '\u3072\u3082\u4e2d\u592e', wBtn1, colors['B'], 1, 1, '\u3068\u3082\u7de8\u307f', 'ab');\n        } else if (l1str === 'AB') {\n            addRec('\u5074\u9762', '0\u5ea6(\u6c34\u5e73\u30fb\u6a2a)', '\u3072\u3082\u4e2d\u592e', wBtn1, colors['A'], 1, 2, '\u3068\u3082\u7de8\u307f', 'a');\n            addRec('\u5074\u9762', '0\u5ea6(\u6c34\u5e73\u30fb\u6a2a)', '\u3072\u3082\u4e2d\u592e', wBtn1, colors['B'], 2, 2, '\u3068\u3082\u7de8\u307f', 'b');\n        } else if (l1str === 'BA') {\n            addRec('\u5074\u9762', '0\u5ea6(\u6c34\u5e73\u30fb\u6a2a)', '\u3072\u3082\u4e2d\u592e', wBtn1, colors['B'], 1, 2, '\u3068\u3082\u7de8\u307f', 'a');\n            addRec('\u5074\u9762', '0\u5ea6(\u6c34\u5e73\u30fb\u6a2a)', '\u3072\u3082\u4e2d\u592e', wBtn1, colors['A'], 2, 2, '\u3068\u3082\u7de8\u307f', 'b');\n        }\n\n        const l2str = c.l2.join('');\n        if (l2str === 'AA') {\n            addRec('\u5074\u9762', '90\u5ea6(\u5782\u76f4\u30fb\u7e26)', '\u3072\u3082\u4e2d\u592e', wBtn2, colors['A'], 1, 1, '\u3068\u3082\u7de8\u307f', 'cd');\n        } else if (l2str === 'BB') {\n            addRec('\u5074\u9762', '90\u5ea6(\u5782\u76f4\u30fb\u7e26)', '\u3072\u3082\u4e2d\u592e', wBtn2, colors['B'], 1, 1, '\u3068\u3082\u7de8\u307f', 'cd');\n        } else if (l2str === 'AB') {\n            addRec('\u5074\u9762', '90\u5ea6(\u5782\u76f4\u30fb\u7e26)', '\u3072\u3082\u4e2d\u592e', wBtn2, colors['A'], 1, 2, '\u3068\u3082\u7de8\u307f', 'c');\n            addRec('\u5074\u9762', '90\u5ea6(\u5782\u76f4\u30fb\u7e26)', '\u3072\u3082\u4e2d\u592e', wBtn2, colors['B'], 2, 2, '\u3068\u3082\u7de8\u307f', 'd');\n        } else if (l2str === 'BA') {\n            addRec('\u5074\u9762', '90\u5ea6(\u5782\u76f4\u30fb\u7e26)', '\u3072\u3082\u4e2d\u592e', wBtn2, colors['B'], 1, 2, '\u3068\u3082\u7de8\u307f', 'c');\n            addRec('\u5074\u9762', '90\u5ea6(\u5782\u76f4\u30fb\u7e26)', '\u3072\u3082\u4e2d\u592e', wBtn2, colors['A'], 2, 2, '\u3068\u3082\u7de8\u307f', 'd');\n        }\n\n        const tableHtml = `\n            <table style=\"width:100%; border-collapse: collapse; font-size: 0.8rem; text-align: left;\">\n                <thead>\n                    <tr style=\"background-color: #f1f1f1;\">\n                        <th style=\"border: 1px solid #ccc; padding: 4px; white-space: nowrap;\">\u756a\u53f7<\/th>\n                        <th style=\"border: 1px solid #ccc; padding: 4px; white-space: nowrap;\">\u914d\u7f6e\u9762<\/th>\n                        <th style=\"border: 1px solid #ccc; padding: 4px; white-space: nowrap;\">\u89d2\u5ea6<\/th>\n                        <th style=\"border: 1px solid #ccc; padding: 4px; white-space: nowrap;\">\u4e2d\u5fc3\u70b9<\/th>\n                        <th style=\"border: 1px solid #ccc; padding: 4px; white-space: nowrap;\">\u4f55\u672c\u5e45<\/th>\n                        <th style=\"border: 1px solid #ccc; padding: 4px; white-space: nowrap;\">\u8272<\/th>\n                        <th style=\"border: 1px solid #ccc; padding: 4px; white-space: nowrap;\">\u958b\u59cb\u4f4d\u7f6e<\/th>\n                        <th style=\"border: 1px solid #ccc; padding: 4px; white-space: nowrap;\">\u4f55\u672c\u3054\u3068<\/th>\n                        <th style=\"border: 1px solid #ccc; padding: 4px; white-space: nowrap;\">\u5dee\u3057\u4f4d\u7f6e<\/th>\n                        <th style=\"border: 1px solid #ccc; padding: 4px; white-space: nowrap;\">\u30e1\u30e2<\/th>\n                    <\/tr>\n                <\/thead>\n                <tbody>\n                    ${records.join('')}\n                <\/tbody>\n            <\/table>\n        `;\n\n        let html = `\n            <div style=\"margin-bottom: 15px;\">\n                <strong>[\u5074\u9762\u3068\u7e01]\u306e\u30bf\u30d6<\/strong> (\u2460\u2461)<br>\n                ${b12} \u2192 \u300c${txt12}\u300d\n            <\/div>\n            <div style=\"margin-bottom: 15px;\">\n                <strong>[\u7e26\u3072\u3082]\u304b\u3089[\u6a2a\u3072\u3082]\u306b\u7d9a\u304f\u30bf\u30d6<\/strong> (\u2462\u2463)<br>\n                ${b34} \u2192 \u300c${txt34}\u300d\n            <\/div>\n            <div>\n                <strong>[\u5dee\u3057\u3072\u3082]\u306e\u30bf\u30d6<\/strong><br>\n                ${tableHtml}\n            <\/div>\n        `;\n        \n        el('#craftBandSquarePanel').innerHTML = html;\n        el('#craftBandSquarePanel').style.display = 'block';\n    };\n\n    el('#btnCraftBandOut').onclick = () => {\n        const panel = el('#craftBandSquarePanel');\n        let shouldGen = false;\n        if (panel.style.display === 'none') shouldGen = true;\n        if (panel.innerHTML.trim() === '') shouldGen = true;\n\n        if (shouldGen) {\n            generateCraftBandOutput();\n        } else {\n            panel.style.display = 'none';\n        }\n    };\n\n    \/\/ --- PDF Download ---\n    el('#btnPdfDownload').onclick = async () => {\n        try {\n            let libsReady = false;\n            if (window.html2canvas) {\n                if (window.jspdf) {\n                    if (window.jspdf.jsPDF) {\n                        libsReady = true;\n                    }\n                }\n            }\n            if (!libsReady) {\n                alert(\"PDF\u30e9\u30a4\u30d6\u30e9\u30ea\u304c\u30ed\u30fc\u30c9\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\");\n                return;\n            }\n            const target = el('#along-lines-calc-app');\n            const canvas = await window.html2canvas(target, { scale: 2, backgroundColor: '#ffffff' });\n            const imgData = canvas.toDataURL('image\/jpeg', 0.95);\n            \n            const pdf = new window.jspdf.jsPDF({ orientation: \"portrait\", unit: \"mm\", format: \"a4\" });\n            const pdfWidth = 210;\n            const pageHeight = 297;\n            const margin = 10;\n            const maxImgW = pdfWidth - margin * 2;\n            const maxImgH = pageHeight - margin * 2;\n            \n            let imgW = maxImgW;\n            let imgH = (canvas.height * imgW) \/ canvas.width;\n            \n            const diffH = imgH - maxImgH;\n            if (Math.sign(diffH) === 1) {\n                imgH = maxImgH;\n                imgW = (canvas.width * imgH) \/ canvas.height;\n            }\n            \n            const xPos = (pdfWidth - imgW) \/ 2;\n            pdf.addImage(imgData, 'JPEG', xPos, margin, imgW, imgH);\n            pdf.save('along-lines-pattern.pdf');\n        } catch(e) {\n            console.error(e);\n            alert(\"PDF\u306e\u751f\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\");\n        }\n    };\n\n    updateToggles(); draw();\n})();\n\/\/]]>\n<\/script>\n\n\n\n\n<p class=\"has-text-align-right\">2026\/05\/05 Ver.1<\/p>\n\n\n\n<p>[CraftBandSquare\u3078\u306e\u8a2d\u5b9a]\u30dc\u30bf\u30f3\u3092\u30af\u30ea\u30c3\u30af\u3059\u308b\u3068\u3001\u9078\u629e\u3057\u305f\u6a21\u69d8\u3092\u4f5c\u308b\u305f\u3081\u306e\u30c7\u30fc\u30bf\u306e\u4f5c\u308a\u65b9\u304c\u308f\u304b\u308a\u307e\u3059\u3002<br><a href=\"https:\/\/labo.com\/CraftBand\/craftbandsquare\/\" data-type=\"page\" data-id=\"1826\">CraftBandSquare<\/a> \u3067\u306f3\u8272\u4ee5\u4e0a\u306e\u7d44\u307f\u5408\u308f\u305b\u3084\u5358\u4f4d\u5909\u66f4\u3001\u307e\u305f\u5168\u4f53\u306e\u30b5\u30a4\u30ba\u3084\u914d\u7f6e\u3092\u30c7\u30b6\u30a4\u30f3\u30fb\u30d7\u30ec\u30d3\u30e5\u30fc\u3067\u304d\u307e\u3059\u306e\u3067\u3001\u5408\u308f\u305b\u3066\u4f7f\u3046\u3068\u4fbf\u5229\u3067\u3059\u3002<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A\u8272\u3068B \u8272\u3092\u30af\u30ea\u30c3\u30af\u3067\u5207\u308a\u66ff\u3048\u3066\u304f\u3060\u3055\u3044\u3002 \u30ec\u30d9\u30eb1-\u7e26\u6a2a\u30b9\u30c6\u30c3\u30c1\u306e\u6700\u5c0f\u5358\u4f4d\u304b\u3089\u4f5c\u3089\u308c\u308b\u69d8\u3005\u306a\u6a21\u69d8\u3092\u3001\u305d\u306e\u5834\u3067\u7c21\u5358\u306b\u898b\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u6587\u5b57\u306e\u4f4d\u7f6e\u306f\u30d0\u30f3\u30c9\u306e\u914d\u7f6e\u3092\u793a\u3057\u3066\u3044\u307e\u3059\u306e\u3067\u3001\u305d\u306e\u901a\u308a\u306b\u7de8\u3080\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002 \u203b\u30b9\u30c6 &hellip; <a href=\"https:\/\/labo.com\/CraftBand\/sharing\/along-lines-calc\/\" class=\"more-link\">\u7d9a\u304d\u3092\u8aad\u3080 <span class=\"screen-reader-text\">\u7e26\u6a2a\u306e\u30b9\u30c6\u30c3\u30c1\u30fb2\u8272\u306e\u7d44\u5408\u305b\u6a21\u69d8<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"parent":688,"menu_order":103,"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-12238","page","type-page","status-publish","hentry"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/labo.com\/CraftBand\/wp-json\/wp\/v2\/pages\/12238"}],"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=12238"}],"version-history":[{"count":10,"href":"https:\/\/labo.com\/CraftBand\/wp-json\/wp\/v2\/pages\/12238\/revisions"}],"predecessor-version":[{"id":12276,"href":"https:\/\/labo.com\/CraftBand\/wp-json\/wp\/v2\/pages\/12238\/revisions\/12276"}],"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=12238"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}