eraser ลบตรายาง (STAMP) ของตัวเองได้: hit-test ใน InkLayer.eraseAt ด้วย bbox จาก annotationBBox (สูตรเดียวกับ render) เช็คตราก่อนเส้น/รูปทรงเพราะตราอยู่ layer บน — ตอน tool erase ค่า TextboxStampLayer ปิด pointer-events อยู่แล้วจึงไม่ต้องแตะ layer stack

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
DESKTOP-1R2VSQH\Lenovo ThinkPad E490 2026-09-14 09:59:01 +07:00
parent 3026e30b34
commit 4934b9d0b3
3 changed files with 26 additions and 4 deletions

View file

@ -20,7 +20,8 @@ import {
type Rect,
type Size,
} from "@/utils/coordinates";
import { hitTestPath, hitTestShape } from "@/utils/geometry";
import { annotationBBox, hitTestPath, hitTestShape } from "@/utils/geometry";
import type { InkStamp } from "./TextboxStampLayer";
/** เส้นวาดที่เก็บใน DB — จุดทุกจุดเป็น % ของหน้า, strokeWidth เป็น % ของความกว้าง */
export type InkStroke = {
@ -79,6 +80,7 @@ export default function InkLayer({
size,
strokes,
shapes,
stamps,
redactions,
active,
nextStroke,
@ -97,6 +99,8 @@ export default function InkLayer({
strokes: InkStroke[];
/** รูปทรงเดิมจาก DB (พิกัด %) */
shapes: InkShape[];
/** ตรายางเดิมจาก DB (พิกัด %) — render ที่ TextboxStampLayer แต่ eraser hit-test ที่นี่ */
stamps: InkStamp[];
/** ปิดพรางเดิมจาก DB (พิกัด %) — วาดทับบังข้อความจริงบนจอ (F8) */
redactions: InkRedaction[];
/** tool วาด/รูปทรง/eraser/redact → รับ pointer events */
@ -289,11 +293,27 @@ export default function InkLayer({
}
}
/** hit-test ตำแหน่ง pointer กับเส้น/รูปทรง **ของตัวเอง** — โดนเมื่อไรลบทันทีทีละรายการ (F6) */
/** hit-test ตำแหน่ง pointer กับเส้น/รูปทรง/ตรายาง **ของตัวเอง** — โดนเมื่อไรลบทันทีทีละรายการ (F6) */
function eraseAt(e: ReactPointerEvent<HTMLDivElement>) {
if (!onErase || ownUserId === "") return;
const p = pointToPercent(toLocalPx(e), measured);
const lp = toLocalPx(e);
const p = pointToPercent(lp, measured);
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) {
if (s.userId !== ownUserId) continue;
const threshold = toPx(s.strokeWidthPct, measured.width) / 2 + pad;

View file

@ -853,6 +853,7 @@ function PdfPage({
strokes={inkStrokes}
shapes={inkShapes}
redactions={inkRedactions}
stamps={inkStamps}
active={inkActive}
nextStroke={{
color: drawStyle.color,