Сканирование: овал-подсказка для лица + запас 10% при захвате (голова не обрезается)

This commit is contained in:
apuc committed 2026-09-17 15:07:45 +03:00
1 parent e7f13f1c83
commit 5bbbe2303c
1 file changed
+16 -3
+16 -3
View File
@@ -190,6 +190,16 @@
object-fit: cover;
transform: scaleX(-1);
}
/* Овал — безопасная зона: лицо должно помещаться в него целиком */
.scan-oval {
position: absolute;
inset: 12%;
border: 3px solid rgba(255, 255, 255, 0.9);
border-radius: 50%;
box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.4);
pointer-events: none;
z-index: 2;
}
.scan-progress { color: #fff; margin-top: 20px; font-size: 16px; text-align: center; }
.scan-progress-bar {
width: 280px;
@@ -414,6 +424,7 @@
<div class="scan-modal" id="scanModal">
<div class="scan-video-wrap">
<video class="scan-video" id="scanVideo" autoplay playsinline muted></video>
<div class="scan-oval"></div>
</div>
<div class="scan-progress">
<div id="scanProgressText">Кадров: 0 / 300 (0%)</div>
@@ -422,7 +433,7 @@
</div>
</div>
<button class="scan-cancel" id="scanCancelBtn">✖ Отмена</button>
<div class="scan-hint">Держите лицо в круге, смотрите прямо в камеру, не двигайтесь</div>
<div class="scan-hint">Поместите лицо в овал целиком: лоб, глаза и подбородок — с запасом. Если голова не помещается — отодвиньте телефон</div>
</div>
<script>
@@ -719,11 +730,13 @@
return;
}
if (ts - scanLastFrameTime >= FRAME_INTERVAL) {
// Квадратный center-crop: берём центральную квадратную область из видео.
// Квадратный center-crop с запасом 10%: берём чуть меньший
// квадрат, чтобы голова гарантированно помещалась целиком
// (иначе SDK не находит лицо из-за обрезанной головы).
const vw = scanVideo.videoWidth;
const vh = scanVideo.videoHeight;
if (vw && vh) {
const side = Math.min(vw, vh);
const side = Math.min(vw, vh) * 0.9;
const sx = (vw - side) / 2;
const sy = (vh - side) / 2;
scanCtx.drawImage(scanVideo, sx, sy, side, side, 0, 0, 1080, 1080);