fix: align calibration clicks with displayed frame

This commit is contained in:
Yoilun
2026-04-27 12:50:49 +08:00
parent 5b747bd1d8
commit cda586a197
2 changed files with 62 additions and 8 deletions

View File

@@ -91,17 +91,43 @@ function addPoint(event) {
setStatus("请先抓取一帧"); setStatus("请先抓取一帧");
return; return;
} }
const rect = canvas.getBoundingClientRect(); const imageRect = getCanvasImageRect();
const scaleX = canvas.width / rect.width; const rawX = event.clientX - imageRect.left;
const scaleY = canvas.height / rect.height; const rawY = event.clientY - imageRect.top;
if (rawX < 0 || rawY < 0 || rawX > imageRect.width || rawY > imageRect.height) {
setStatus("请点击截图实际显示区域内");
return;
}
const point = { const point = {
x: clamp(((event.clientX - rect.left) * scaleX) / canvas.width), x: clamp(rawX / imageRect.width),
y: clamp(((event.clientY - rect.top) * scaleY) / canvas.height), y: clamp(rawY / imageRect.height),
}; };
state.polygons[state.activeZone].push(point); state.polygons[state.activeZone].push(point);
render(); render();
} }
function getCanvasImageRect() {
const rect = canvas.getBoundingClientRect();
const canvasRatio = canvas.width / canvas.height;
const elementRatio = rect.width / rect.height;
if (elementRatio > canvasRatio) {
const width = rect.height * canvasRatio;
return {
left: rect.left + (rect.width - width) / 2,
top: rect.top,
width,
height: rect.height,
};
}
const height = rect.width / canvasRatio;
return {
left: rect.left,
top: rect.top + (rect.height - height) / 2,
width: rect.width,
height,
};
}
function undoPoint() { function undoPoint() {
state.polygons[state.activeZone].pop(); state.polygons[state.activeZone].pop();
render(); render();

View File

@@ -325,13 +325,41 @@ function addPoint(event) {
setStatus("请先从 RTSP 抓取一帧"); setStatus("请先从 RTSP 抓取一帧");
return; return;
} }
const rect = els.canvas.getBoundingClientRect(); const imageRect = getCanvasImageRect();
const x = clamp((event.clientX - rect.left) / rect.width); const rawX = event.clientX - imageRect.left;
const y = clamp((event.clientY - rect.top) / rect.height); const rawY = event.clientY - imageRect.top;
if (rawX < 0 || rawY < 0 || rawX > imageRect.width || rawY > imageRect.height) {
setStatus("请点击截图实际显示区域内");
return;
}
const x = clamp(rawX / imageRect.width);
const y = clamp(rawY / imageRect.height);
state.polygons[state.activeRegion].push({x: round(x), y: round(y)}); state.polygons[state.activeRegion].push({x: round(x), y: round(y)});
render(); render();
} }
function getCanvasImageRect() {
const rect = els.canvas.getBoundingClientRect();
const canvasRatio = els.canvas.width / els.canvas.height;
const elementRatio = rect.width / rect.height;
if (elementRatio > canvasRatio) {
const width = rect.height * canvasRatio;
return {
left: rect.left + (rect.width - width) / 2,
top: rect.top,
width,
height: rect.height,
};
}
const height = rect.width / canvasRatio;
return {
left: rect.left,
top: rect.top + (rect.height - height) / 2,
width: rect.width,
height,
};
}
function undoPoint() { function undoPoint() {
state.polygons[state.activeRegion].pop(); state.polygons[state.activeRegion].pop();
render(); render();