From c8360cd58adb5d5149a02d3f1f20a71828cdccd9 Mon Sep 17 00:00:00 2001 From: Hyungi Ahn Date: Mon, 27 Apr 2026 14:48:50 +0900 Subject: [PATCH] =?UTF-8?q?fix(study):=20=ED=99=95=EB=8C=80=20=ED=9A=8C?= =?UTF-8?q?=EA=B7=80=20=EC=A7=84=EC=A7=9C=20root=20cause=20=E2=80=94=20inl?= =?UTF-8?q?ine=20style=20=EC=9D=98=20reactive=20cursor=20=EA=B0=80=20imper?= =?UTF-8?q?ative=20width=20=EB=8D=AE=EC=96=B4=EC=94=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 진단 도구로 확정: 펜 클릭 시 canvas:1512×677 정상 → 지우개 클릭 시 canvas:3024×1354 정확히 2배 (= cssWidth × dpr). canvas.style.width 가 사라져 internal pixel 그대로 displayed → 화면상 2배 확대. 원인: 가 reactive variable (tool) 포함한 inline style. tool 변경 시 Svelte 가 inline style attribute *전체* 재설정 → resizeCanvas() 의 imperative `canvas.style.width = ...px` 가 덮어써져 사라짐. 새로고침 / 창 이동 시 resizeCanvas 다시 호출되며 복구되던 이유. Fix: - style:cursor / style:width / style:height directive 로 분리. Svelte 의 style:property 는 해당 property 만 set 하고 다른 inline style 안 건드림. - 정적 inline style="..." 에서 cursor 제거. - resizeCanvas 의 imperative style.width/height 라인 제거 (svelte directive 가 처리). 내부 pixel 은 그대로 imperative set 유지 (canvas.width = cssWidth × dpr — DOM attribute 라 inline style 과 별개). Co-Authored-By: Claude Opus 4.7 (1M context) --- frontend/src/lib/components/HandwriteCanvas.svelte | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/frontend/src/lib/components/HandwriteCanvas.svelte b/frontend/src/lib/components/HandwriteCanvas.svelte index ee5eb4e..892b3f5 100644 --- a/frontend/src/lib/components/HandwriteCanvas.svelte +++ b/frontend/src/lib/components/HandwriteCanvas.svelte @@ -159,8 +159,10 @@ const dpr = window.devicePixelRatio || 1; canvas.width = cssWidth * dpr; canvas.height = cssHeight * dpr; - canvas.style.width = `${cssWidth}px`; - canvas.style.height = `${cssHeight}px`; + // canvas.style.width/height 는 svelte 의 style:width / style:height directive 가 + // reactive 로 처리. imperative set 은 inline style="..." 의 reactive 변수 + // (예: style="cursor: {tool}") 갱신 시 함께 덮어써서 사라지는 회귀 (확대 = canvas + // 가 internal pixel 그대로 displayed) 의 원인이었음. const ctx = canvas.getContext('2d'); if (ctx) ctx.setTransform(dpr, 0, 0, dpr, 0, 0); scheduleRedraw(); @@ -802,7 +804,10 @@ oncontextmenu={(e) => e.preventDefault()} onselectstart={(e) => e.preventDefault()} class="block" - style="touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; cursor: {tool === 'eraser' ? 'cell' : 'crosshair'};" + style:cursor={tool === 'eraser' ? 'cell' : 'crosshair'} + style:width={cssWidth ? `${cssWidth}px` : undefined} + style:height={cssHeight ? `${cssHeight}px` : undefined} + style="touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent;" > {#if DBG}