BSB_Sim/app/static/capture.js
2026-10-19 08:11:33 +02:00

98 lines
3.2 KiB
JavaScript

(() => {
const canvas = document.getElementById("pad");
const context = canvas.getContext("2d");
const userId = document.getElementById("user-id");
const status = document.getElementById("status");
const points = [];
let drawing = false;
let startTime = 0;
context.lineWidth = 3;
context.lineCap = "round";
context.lineJoin = "round";
function pointFrom(event, penDown) {
const bounds = canvas.getBoundingClientRect();
const scaleX = canvas.width / bounds.width;
const scaleY = canvas.height / bounds.height;
return {
t: performance.now() - startTime,
x: (event.clientX - bounds.left) * scaleX,
y: (event.clientY - bounds.top) * scaleY,
p: event.pressure || (penDown ? 0.5 : 0),
area: event.width * event.height,
pen_down: penDown,
};
}
canvas.addEventListener("pointerdown", (event) => {
event.preventDefault();
canvas.setPointerCapture(event.pointerId);
if (points.length === 0) startTime = performance.now();
drawing = true;
const point = pointFrom(event, true);
points.push(point);
context.beginPath();
context.moveTo(point.x, point.y);
});
canvas.addEventListener("pointermove", (event) => {
if (!drawing) return;
const point = pointFrom(event, true);
points.push(point);
context.lineTo(point.x, point.y);
context.stroke();
});
function endStroke(event) {
if (!drawing) return;
points.push(pointFrom(event, false));
drawing = false;
}
canvas.addEventListener("pointerup", endStroke);
canvas.addEventListener("pointercancel", endStroke);
document.getElementById("clear").addEventListener("click", () => {
points.length = 0;
context.clearRect(0, 0, canvas.width, canvas.height);
status.textContent = "Signature cleared.";
});
async function send(path) {
if (!userId.value.trim()) {
status.textContent = "Enter a participant ID first.";
return;
}
if (points.filter((point) => point.pen_down).length < 2) {
status.textContent = "Draw a signature with at least two points.";
return;
}
const payload = {
user_id: userId.value.trim(),
t: points.map((point) => point.t),
x: points.map((point) => point.x),
y: points.map((point) => point.y),
p: points.map((point) => point.p),
area: points.map((point) => point.area),
pen_down: points.map((point) => point.pen_down),
};
status.textContent = "Sending…";
try {
const response = await fetch(path, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
});
const result = await response.json();
if (!response.ok) throw new Error(result.detail || `Request failed (${response.status})`);
status.textContent = path === "/verify"
? `Accepted: ${result.accepted}; score: ${result.score.toFixed(3)}; threshold: ${result.threshold.toFixed(3)}`
: `Enrolled sample for ${result.user_id}. Enroll multiple genuine samples.`;
} catch (error) {
status.textContent = `Error: ${error.message}`;
}
}
document.getElementById("enroll").addEventListener("click", () => send("/enroll"));
document.getElementById("verify").addEventListener("click", () => send("/verify"));
})();