eCourt-note/.claude/rules/coordinates.md
DESKTOP-1R2VSQH\Lenovo ThinkPad E490 eddcec28c7 Add application codebase: PDF annotation for e-Court
Next.js 14 + Drizzle/PostgreSQL + SSE realtime sync — highlight,
freehand, comment, bookmark + ฟีเจอร์ต่อยอด F1–F19 (edit/move, undo/redo,
shapes, redaction, export PDF/CSV, reply, resolve, search, summary,
textbox, stamp, version history)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-10 14:29:40 +07:00

2 KiB
Raw Blame History

paths
utils/coordinates.ts
utils/geometry.ts
components/pdf/InkLayer.tsx
components/pdf/AnnotationSelectionLayer.tsx

Coordinate Rules (รายละเอียด: docs/PLAN.md §2)

  • ทิศทางแปลง: px → % = ÷size×100, % → px = ×size÷100 — ครบทั้ง point/rect/path
  • strokeWidth เก็บเป็น % ของความกว้างหน้า; yOffset เก็บเป็น % ของความสูงหน้า (0–100)
  • mergeRectsByLine(rects): จัดกลุ่ม rects ที่ y/height ใกล้กัน (บรรทัดเดียวกัน) → union แกน x → คืน 1 rect ต่อบรรทัด — เรียกทุกครั้งก่อนบันทึก HIGHLIGHT ลง DB
  • InkLayer: SVG ห้ามมี viewBox (ความหนาเส้นจะบิดเบี้ยวเมื่อ scale แกน x/y ไม่เท่ากัน) — render ระบบ px จริง แปลง % → px ด้วยขนาดจาก ResizeObserver แล้ว re-render เมื่อ resize/zoom
  • พิกัดจาก event ใช้ getBoundingClientRect() ของ page element เป็นฐานเสมอ และ clamp ค่า % ให้อยู่ 0–100
  • utils/geometry.ts (PLAN-FEAT.md F1) — pure functions บนพิกัด %: annotationBBox / translateAnnotationData / scaleAnnotationData / hitTestPath — ก่อนส่ง data ที่แปลงแล้วเข้า updateAnnotation ต้อง clamp offset/scale ให้ bbox ทั้งกลุ่มอยู่ใน 0–100 เพราะ validator ปฏิเสธค่าติดลบ
  • AnnotationSelectionLayer: container pointer-events: none เสมอ เฉพาะ handle มุม/ขอบกรอบ/แถบเครื่องมือที่ auto — ห้ามให้กรอบ selection บัง textLayer