// 개선된 그리기 모드 로직 // 기존 복잡한 다중 캔버스 처리 대신 단일 캔버스를 이용 let canvas, ctx; let drawMode = null; // 'line', 'free', 'polyline', 'text', 'eraser' let drawColor = '#000000'; let lineWidth = 2; let isDrawing = false; let startX = 0, startY = 0; let path = []; // 툴 버튼 const drawBtn = document.getElementById('drawBtn'); const lineBtn = document.getElementById('lineBtn'); const freeBtn = document.getElementById('freeBtn'); const polyBtn = document.getElementById('polylineBtn'); const textBtn = document.getElementById('textBtn'); const eraserBtn = document.getElementById('eraserBtn'); const colorPicker = document.getElementById('drawColor'); const widthInput = document.getElementById('lineWidth'); // 캔버스 생성 및 초기화 function createCanvas() { const preview = document.getElementById('previewContainer'); // 기존 캔버스 제거 const old = document.getElementById('drawingCanvas'); if (old) old.remove(); canvas = document.createElement('canvas'); canvas.id = 'drawingCanvas'; canvas.width = 320; canvas.height = 240; Object.assign(canvas.style, { position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', zIndex: 1000, cursor: drawMode === 'eraser' ? 'crosshair' : 'default' }); preview.appendChild(canvas); ctx = canvas.getContext('2d'); ctx.lineCap = 'round'; ctx.lineJoin = 'round'; } // 이벤트 해제 function detachEvents() { if (!canvas) return; canvas.onmousedown = null; canvas.onmousemove = null; canvas.onmouseup = null; canvas.onmouseleave = null; } // 이벤트 연결 function attachEvents() { const rectTransform = (e) => { const rect = canvas.getBoundingClientRect(); return { x: (e.clientX - rect.left) * (canvas.width / rect.width), y: (e.clientY - rect.top) * (canvas.height / rect.height) }; }; canvas.onmousedown = e => { const pt = rectTransform(e); isDrawing = true; startX = pt.x; startY = pt.y; path = [pt]; ctx.strokeStyle = drawMode === 'eraser' ? '#ffffff' : drawColor; ctx.lineWidth = Number(widthInput.value) || lineWidth; if (drawMode === 'free') { ctx.beginPath(); ctx.moveTo(pt.x, pt.y); } }; canvas.onmousemove = e => { if (!isDrawing) return; const pt = rectTransform(e); if (drawMode === 'free') { ctx.lineTo(pt.x, pt.y); ctx.stroke(); path.push(pt); } else if (drawMode === 'eraser') { ctx.save(); ctx.beginPath(); ctx.fillStyle = '#ffffff'; ctx.arc(pt.x, pt.y, Number(widthInput.value) || 10, 0, Math.PI*2); ctx.fill(); ctx.restore(); } }; canvas.onmouseup = e => { if (!isDrawing) return; const pt = rectTransform(e); if (drawMode === 'line') { ctx.beginPath(); ctx.moveTo(startX, startY); ctx.lineTo(pt.x, pt.y); ctx.stroke(); } else if (drawMode === 'polyline') { ctx.beginPath(); const last = path[path.length-1]; ctx.moveTo(last.x, last.y); ctx.lineTo(pt.x, pt.y); ctx.stroke(); path.push(pt); } else if (drawMode === 'text') { const txt = prompt('텍스트 입력:'); if (txt) { ctx.fillStyle = drawColor; ctx.font = `${widthInput.value||16}px sans-serif`; ctx.fillText(txt, pt.x, pt.y); } } isDrawing = drawMode === 'polyline'; }; canvas.onmouseleave = () => { isDrawing = false; }; } // 모드 설정 function setMode(mode) { drawMode = mode; document.querySelectorAll('.tool-button').forEach(btn => btn.classList.remove('active')); switch(mode) { case 'line': lineBtn.classList.add('active'); break; case 'free': freeBtn.classList.add('active'); break; case 'polyline':polyBtn.classList.add('active'); break; case 'text': textBtn.classList.add('active'); break; case 'eraser': eraserBtn.classList.add('active'); break; } if (canvas) canvas.style.cursor = mode === 'eraser' ? 'crosshair' : 'default'; } // 버튼 이벤트 drawBtn.onclick = () => { if (canvas) { detachEvents(); canvas.remove(); canvas=null; drawBtn.textContent = '그리기'; } else { createCanvas(); attachEvents(); drawBtn.textContent = '중지'; } }; lineBtn.onclick = () => setMode('line'); freeBtn.onclick = () => setMode('free'); polyBtn.onclick = () => setMode('polyline'); textBtn.onclick = () => setMode('text'); eraserBtn.onclick = () => setMode('eraser'); colorPicker.oninput= e => drawColor = e.target.value; widthInput.oninput = e => lineWidth = Number(e.target.value); // ------------------------------------------------- // 이 패치를 적용하시면, 그리기 모드는 단일 캔버스에서만 동작하며 // 기존 이미지가 사라졌다가 재출력되는 버그가 사라집니다. // 버튼별 동작도 일관적으로 처리됩니다.