diff --git a/frontend/src/lib/components/HandwriteCanvas.svelte b/frontend/src/lib/components/HandwriteCanvas.svelte index 338f237..bb615bf 100644 --- a/frontend/src/lib/components/HandwriteCanvas.svelte +++ b/frontend/src/lib/components/HandwriteCanvas.svelte @@ -214,8 +214,9 @@ if (!path) { const outline = getStroke(pts, { size, - // thinning 0 — pressure 변동에 stroke 폭 영향 안 받음. 흔들림 1차 차단. - thinning: 0, + // thinning 0.15 — pressure 변동에 stroke 폭 ±15% 반응. EMA 로 부드럽게 + // smooth 된 pressure 와 조합 → Notability 같은 자연스러운 굵기 흐름. + thinning: 0.15, // smoothing 0.99 — 점 간 보간 사실상 최대. smoothing: 0.99, // streamline 0.86 — input lazy 강하게. 손떨림 보정 + 부드러움. 0.9 이상은 lag. @@ -336,13 +337,12 @@ // 점 사이 거리가 너무 멀면 중간 점 보간 — 빠른 stroke 의 sparse point 점선 방지. // iPad 60Hz pointermove + 빠른 펜 이동 시 점 간격이 16~30px 가 될 수 있음. const MAX_GAP_PX = 8; - // pressure 변동 limit — 만년필 효과: 약한 압력에도 부드럽게, 점 간 압력 차이가 - // 너무 크면 stroke 폭이 들쭉날쭉해짐. 한 점당 5% 이내로만 변동. - const PRESSURE_SMOOTH_RATE = 0.05; + // pressure EMA — 점 간 pressure 변동을 *지수 이동 평균* 으로 부드럽게. + // alpha 0.15 = 새 값 15% + 이전 값 85% 가중. 잡음/덜컥 변동 제거 + Notability + // 같은 자연스러운 흐름. thinning=0.15 와 조합 시 stroke 굵기가 부드럽게 변함. + const PRESSURE_EMA_ALPHA = 0.15; function smoothPressure(prev: number, current: number): number { - const dp = current - prev; - if (Math.abs(dp) <= PRESSURE_SMOOTH_RATE) return current; - return prev + Math.sign(dp) * PRESSURE_SMOOTH_RATE; + return prev + (current - prev) * PRESSURE_EMA_ALPHA; } function pushPointWithInterp(target: Stroke, x: number, y: number, p: number) { const last = target.points[target.points.length - 1];