// camera.ts import { updateResizerVisibility } from './layout.js'; let rightPanel = null; let camImage = null; let crosshair = null; let isOpen = false; let streamCheckInterval = null; export function initCamera() { rightPanel = document.getElementById("rightPanel"); camImage = document.getElementById("camImage"); crosshair = document.getElementById("crosshair"); // Проверяем доступность потока checkStreamAvailability(); const btn = document.getElementById("camToggle"); const streamUrl = "/api/cam"; function open() { if (isOpen) return; isOpen = true; if (rightPanel) { rightPanel.classList.remove("hidden"); } // Показываем перекрестие if (crosshair) { crosshair.style.display = "block"; } if (camImage) { camImage.src = streamUrl; } if (btn) { const textSpan = btn.querySelector('.cam-btn-text'); if (textSpan) textSpan.textContent = 'Скрыть'; } console.log("[camera] opened"); updateResizerVisibility(); // Запускаем мониторинг потока startStreamMonitoring(); } function close() { if (!isOpen) return; isOpen = false; // Скрываем перекрестие if (crosshair) { crosshair.style.display = "none"; } // остановка stream if (camImage) { camImage.src = ""; } if (rightPanel) { rightPanel.classList.add("hidden"); } if (btn) { const textSpan = btn.querySelector('.cam-btn-text'); if (textSpan) textSpan.textContent = 'Камера'; } console.log("[camera] closed"); updateResizerVisibility(); // Останавливаем мониторинг stopStreamMonitoring(); } function toggle() { if (isOpen) { close(); } else { open(); } } if (camImage) { camImage.onload = () => { console.log("[camera] stream started"); if (crosshair) { crosshair.style.opacity = '1'; } }; camImage.onerror = (e) => { console.error("[camera] stream error", e); if (crosshair) { crosshair.style.opacity = '0.3'; } }; } btn?.addEventListener("click", toggle); // Проверка доступности камеры async function checkStreamAvailability() { try { const response = await fetch('/api/stream'); const data = await response.json(); if (data.available && data.cam) { console.log("[camera] stream available:", data.source); // Автозапуск если камера доступна if (!isOpen) { open(); } } else { console.log("[camera] stream not available"); if (crosshair) { crosshair.style.display = 'none'; } } } catch (error) { console.log("[camera] check failed:", error); } } // Мониторинг состояния потока function startStreamMonitoring() { stopStreamMonitoring(); streamCheckInterval = window.setInterval(() => { if (isOpen && camImage) { if (!camImage.complete || camImage.naturalWidth === 0) { if (crosshair) { crosshair.style.opacity = '0.3'; } } else { if (crosshair) { crosshair.style.opacity = '1'; } } } }, 2000); } function stopStreamMonitoring() { if (streamCheckInterval) { clearInterval(streamCheckInterval); streamCheckInterval = null; } } } // Экспортируем для возможности ручного управления export function showCrosshair(show = true) { const crosshairElem = document.getElementById("crosshair"); if (crosshairElem) { crosshairElem.style.display = show ? "block" : "none"; } } export function setCrosshairOpacity(opacity) { const crosshairElem = document.getElementById("crosshair"); if (crosshairElem) { crosshairElem.style.opacity = String(opacity); } }