Compare commits
No commits in common. "4934b9d0b388775afd41e4b63a50025d37645e22" and "1c2f4c834a448ecccc77ccb7dd2b867a36a138ac" have entirely different histories.
4934b9d0b3
...
1c2f4c834a
4 changed files with 4 additions and 31 deletions
|
|
@ -90,10 +90,5 @@
|
||||||
header .touch-44 > div > a {
|
header .touch-44 > div > a {
|
||||||
min-height: 2.75rem;
|
min-height: 2.75rem;
|
||||||
min-width: 2.75rem;
|
min-width: 2.75rem;
|
||||||
/* min 44px ทำให้ปุ่ม icon เดี่ยวกว้างเกิน content — ต้อง center icon
|
|
||||||
ไม่งั้นชิดซ้าย+ลอยตาม baseline (ปุ่ม dropdown มี flex อยู่แล้ว ไม่กระทบ) */
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,7 @@ import {
|
||||||
type Rect,
|
type Rect,
|
||||||
type Size,
|
type Size,
|
||||||
} from "@/utils/coordinates";
|
} from "@/utils/coordinates";
|
||||||
import { annotationBBox, hitTestPath, hitTestShape } from "@/utils/geometry";
|
import { hitTestPath, hitTestShape } from "@/utils/geometry";
|
||||||
import type { InkStamp } from "./TextboxStampLayer";
|
|
||||||
|
|
||||||
/** เส้นวาดที่เก็บใน DB — จุดทุกจุดเป็น % ของหน้า, strokeWidth เป็น % ของความกว้าง */
|
/** เส้นวาดที่เก็บใน DB — จุดทุกจุดเป็น % ของหน้า, strokeWidth เป็น % ของความกว้าง */
|
||||||
export type InkStroke = {
|
export type InkStroke = {
|
||||||
|
|
@ -80,7 +79,6 @@ export default function InkLayer({
|
||||||
size,
|
size,
|
||||||
strokes,
|
strokes,
|
||||||
shapes,
|
shapes,
|
||||||
stamps,
|
|
||||||
redactions,
|
redactions,
|
||||||
active,
|
active,
|
||||||
nextStroke,
|
nextStroke,
|
||||||
|
|
@ -99,8 +97,6 @@ export default function InkLayer({
|
||||||
strokes: InkStroke[];
|
strokes: InkStroke[];
|
||||||
/** รูปทรงเดิมจาก DB (พิกัด %) */
|
/** รูปทรงเดิมจาก DB (พิกัด %) */
|
||||||
shapes: InkShape[];
|
shapes: InkShape[];
|
||||||
/** ตรายางเดิมจาก DB (พิกัด %) — render ที่ TextboxStampLayer แต่ eraser hit-test ที่นี่ */
|
|
||||||
stamps: InkStamp[];
|
|
||||||
/** ปิดพรางเดิมจาก DB (พิกัด %) — วาดทับบังข้อความจริงบนจอ (F8) */
|
/** ปิดพรางเดิมจาก DB (พิกัด %) — วาดทับบังข้อความจริงบนจอ (F8) */
|
||||||
redactions: InkRedaction[];
|
redactions: InkRedaction[];
|
||||||
/** tool วาด/รูปทรง/eraser/redact → รับ pointer events */
|
/** tool วาด/รูปทรง/eraser/redact → รับ pointer events */
|
||||||
|
|
@ -293,27 +289,11 @@ export default function InkLayer({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** hit-test ตำแหน่ง pointer กับเส้น/รูปทรง/ตรายาง **ของตัวเอง** — โดนเมื่อไรลบทันทีทีละรายการ (F6) */
|
/** hit-test ตำแหน่ง pointer กับเส้น/รูปทรง **ของตัวเอง** — โดนเมื่อไรลบทันทีทีละรายการ (F6) */
|
||||||
function eraseAt(e: ReactPointerEvent<HTMLDivElement>) {
|
function eraseAt(e: ReactPointerEvent<HTMLDivElement>) {
|
||||||
if (!onErase || ownUserId === "") return;
|
if (!onErase || ownUserId === "") return;
|
||||||
const lp = toLocalPx(e);
|
const p = pointToPercent(toLocalPx(e), measured);
|
||||||
const p = pointToPercent(lp, measured);
|
|
||||||
const pad = 6; // เผื่อความคาดหวังของผู้ใช้นอกเส้นจริง (px)
|
const pad = 6; // เผื่อความคาดหวังของผู้ใช้นอกเส้นจริง (px)
|
||||||
// ตรายาง render อยู่ layer บน (TextboxStampLayer) → เช็คก่อน ให้ตัวบนสุดชนะ
|
|
||||||
// (bbox = สูตรเดียวกับ render และกรอบ selection — annotationBBox)
|
|
||||||
for (const s of stamps) {
|
|
||||||
if (s.userId !== ownUserId) continue;
|
|
||||||
const b = annotationBBox({ type: "STAMP", data: s.data }, measured);
|
|
||||||
if (
|
|
||||||
lp.x >= b.x - pad &&
|
|
||||||
lp.x <= b.x + b.width + pad &&
|
|
||||||
lp.y >= b.y - pad &&
|
|
||||||
lp.y <= b.y + b.height + pad
|
|
||||||
) {
|
|
||||||
onErase(s.id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const s of strokes) {
|
for (const s of strokes) {
|
||||||
if (s.userId !== ownUserId) continue;
|
if (s.userId !== ownUserId) continue;
|
||||||
const threshold = toPx(s.strokeWidthPct, measured.width) / 2 + pad;
|
const threshold = toPx(s.strokeWidthPct, measured.width) / 2 + pad;
|
||||||
|
|
|
||||||
|
|
@ -853,7 +853,6 @@ function PdfPage({
|
||||||
strokes={inkStrokes}
|
strokes={inkStrokes}
|
||||||
shapes={inkShapes}
|
shapes={inkShapes}
|
||||||
redactions={inkRedactions}
|
redactions={inkRedactions}
|
||||||
stamps={inkStamps}
|
|
||||||
active={inkActive}
|
active={inkActive}
|
||||||
nextStroke={{
|
nextStroke={{
|
||||||
color: drawStyle.color,
|
color: drawStyle.color,
|
||||||
|
|
|
||||||
|
|
@ -139,10 +139,9 @@ Index: `(file_id)`
|
||||||
|
|
||||||
### F6 · B3 Eraser
|
### F6 · B3 Eraser
|
||||||
|
|
||||||
- Tool `erase`: InkLayer active (รับ pointer, `touch-action: none`), `pointerdown/move` ทำ hit-test ตำแหน่ง pointer กับเส้น/รูปทรง/ตรายาง **ของตัวเองเท่านั้น** (ส่ง `userId` มากับ strokes):
|
- Tool `erase`: InkLayer active (รับ pointer, `touch-action: none`), `pointerdown/move` ทำ hit-test ตำแหน่ง pointer กับเส้น/รูปทรง **ของตัวเองเท่านั้น** (ส่ง `userId` มากับ strokes):
|
||||||
- DRAW: ระยะจากจุดถึง segment ทุกท่อน ≤ `strokeWidth/2 + 6px`
|
- DRAW: ระยะจากจุดถึง segment ทุกท่อน ≤ `strokeWidth/2 + 6px`
|
||||||
- SHAPE: ระยะถึงเส้นขอบ (stroke) — ลากผ่าน "พื้นที่" รูปทรงไม่โดน (เหมือนสัมผัสเส้นจริง)
|
- SHAPE: ระยะถึงเส้นขอบ (stroke) — ลากผ่าน "พื้นที่" รูปทรงไม่โดน (เหมือนสัมผัสเส้นจริง)
|
||||||
- STAMP: จุดอยู่ใน bbox ของตรา (`annotationBBox` สูตรเดียวกับ render) + 6px — เช็ค**ก่อน**เส้น/รูปทรงเพราะตรา render อยู่ layer บน (TextboxStampLayer) ให้ตัวบนสุดชนะ
|
|
||||||
- โดน = `deleteAnnotation` ทันที (ลากผ่านหลายเส้น = ลบทีละเส้นระหว่างเคลื่อน) — เส้นของคนอื่นไม่ผ่าน hit-test จึงลบไม่ได้
|
- โดน = `deleteAnnotation` ทันที (ลากผ่านหลายเส้น = ลบทีละเส้นระหว่างเคลื่อน) — เส้นของคนอื่นไม่ผ่าน hit-test จึงลบไม่ได้
|
||||||
|
|
||||||
### F8 · B4+C1 Redaction + Export PDF (ทำคู่กันเสมอ — D4)
|
### F8 · B4+C1 Redaction + Export PDF (ทำคู่กันเสมอ — D4)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue