필기감:
- perfect-freehand 재도입 (effect race 제거됐으니 안전)
- thinning 0.6, smoothing 0.65, streamline 0.5
- simulatePressure false → 실제 e.pressure 반영
- outline polygon 을 quadratic bezier 로 연결 → 부드러운 곡선 (직선 segment ❌)
- ctx.fill() anti-aliased
UI:
- 굵기 토글 (가늘게/보통/굵게) — baseSize × {0.6, 1, 1.6}
- Pencil only (touch 차단)
연속 stroke race fix:
- setPointerCapture/release 제거 → 빠른 pointerup→pointerdown race 차단
- onPointerDown 시 이전 inflight 강제 보존 (드물지만 stale 한 경우)
- pointerleave 핸들러는 inflight 가 살아있을 때만 endStroke
- endStroke: inflight 없으면 즉시 return, activePointerId 만 정리
이전 보고: "ㄱ 쓰고 ㅏ 바로 쓰면 ㅏ 가 입력 안됨" 핵심 원인은 stale
pointerleave 가 두번째 stroke 를 강제 종료시킨 것. 위 race fix 로 해결.
- isPenLike: 'touch' 제거. pen/mouse 만 허용 → 손가락 stroke/지우개 차단
- 페이지/툴바 영역에 touch-action: manipulation → 버튼 빠른 두 번 탭 시
iOS Safari 더블탭 줌 차단. 지우개/펜 토글 시 화면 확대되던 현상 fix.
원인: \$effect(initialStrokes 동기화) 가 strokes 도 의존성으로 추적함.
사용자가 펜으로 그린 후 strokes 변경 → effect 재실행 → 조건
"initialStrokes.strokes !== strokes" 가 true → strokes 를 옛 initialStrokes
값으로 되돌림 → 새 stroke 사라짐.
지우개 누르면 글자가 커지는 현상도 같은 effect 가 trigger 되며 strokes 가
옛 값으로 reset + canvas 비율 재계산이 겹쳐 발생.
Fix:
- \$effect 제거. 초기 strokes 는 \$state initial value 로 한 번만 set.
부모가 prop 새 값을 줘도 무시 (사용자 진행 stroke 우선).
- traceText effect 는 명시적 prev 비교로만 redraw 트리거.
- 디버그용 빨간 사각형 / 빨간 strokeStyle 제거. 정상 색 (--text) 복귀.
stroke 가 안 보이는 원인 격리. iPad 화면에서:
- 좌상단 빨간 50x50 사각형 보임 + 빨간 stroke 보임 → 토큰 색 문제
- 사각형 보임 + stroke 안 보임 → drawStroke / strokeStyle 문제
- 사각형도 안 보임 → redraw 미호출 또는 canvas 자체 가려짐
증상: stroke count 는 올라가는데 화면에 그려지지 않음 + 위치 어긋남.
원인 격리 시도:
- perfect-freehand 의 polygon fill 이 일부 환경에서 제대로 그려지지 않는 것으로
보여 단순 ctx.beginPath/moveTo/lineTo/stroke() 로 갈아치움. lineCap/lineJoin
'round' + lineWidth=baseSize 로 자연스러운 라인. 압력 효과는 일시 제거.
- getLocalXY 에 scale 보정 추가: canvas.style.width(cssWidth) 와 rect.width 가
다른 ResizeObserver 지연 케이스에서 좌표가 어긋나지 않도록 비율 보정.
이번 변경으로도 stroke 가 안 보이면 디버그 오버레이의 좌표/크기를 보고
다른 경로 (캔버스 자체 비활성, layer 가림 등) 추적.
증상: iPad 에서 펜 입력이 안 들어가거나 다른 위치에 그려지는 보고. 원인은
좌우 분할 layout 에서 우측 캔버스 영역이 좁거나 layout 이 stale.
UI:
- /study/write/[id] layout 을 캔버스 풀스크린 + 좌측 floating panel 로 변경
- 헤더에 패널 토글 버튼. 패널 default closed → 캔버스가 화면 거의 전체
- 캔버스 컨테이너에 border-default/30 추가 (영역 가시화)
좌표/입력:
- isPenLike: 'touch' 도 허용 (iPad 일부 빌드에서 Pencil 이 'pen' 으로 안 들어오는 케이스 방어)
- 디버그 오버레이: 캔버스 크기 + 마지막 pointer 좌표/pressure/type 표시
- ResizeObserver 외에 window resize / orientationchange 리스너 추가
- 마운트 직후 RAF×2 후 한 번 더 resizeCanvas (flex 레이아웃 0x0 첫 paint 방어)
stroke 가 안 그려지는 이슈 수정 + 사용자 요청한 부분 지우개 추가.
렌더링 fix:
- last:true 항상 (진행 중 stroke 도 양쪽 outline + cap 완성, polygon 닫힘 보장).
이전엔 inflight 일 때 last:false 라서 outline 한쪽만 그려져 fill 영역 거의 0.
- thinning 0.5 → 0.3 (시작/끝 부분이 너무 얇아지지 않게)
- baseSize default 4 → 6
- pointermove: main 점을 항상 push (coalesced 는 보간 보조)
부분 지우개:
- tool: 'pen' | 'eraser' state. 툴바에 펜/지우개 토글
- eraser 모드: pointer 가 지나가는 stroke 를 점-원 hit-test 로 즉시 삭제
- eraserRadius = baseSize * 4 (최소 16 px)
- 삭제된 stroke 는 undoStack 으로 — undo 로 복구 가능
- cursor: eraser 면 'cell', 펜이면 'crosshair'
- 전체 지우기는 별도 Trash2 버튼으로 분리
문제: dark mode 에서 stroke #111 이 --bg #0f1117 와 거의 같아 안 보임 +
Apple Pencil pressure 0 케이스 방어 부재.
수정:
- strokeColor 를 마운트 시 --text 토큰 실측 (e4e4e7 등) 으로 갱신
- simulatePressure true 로 변경 — 압력 0 으로 들어와도 속도 기반으로 굵기 보장
- thinning 0.55 → 0.5