Files
go-service/cmd/server/web/js/camera.js

161 lines
4.2 KiB
JavaScript

// camera.js
import { updateResizerVisibility } from './layout.js';
let rightPanel;
let camImage;
let crosshair;
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;
rightPanel.classList.remove("hidden");
// Показываем перекрестие
if (crosshair) {
crosshair.style.display = "block";
}
camImage.src = streamUrl;
if (btn) {
btn.querySelector('.cam-btn-text').textContent = 'Скрыть';
}
console.log("[camera] opened");
updateResizerVisibility();
// Запускаем мониторинг потока
startStreamMonitoring();
}
function close() {
if (!isOpen) return;
isOpen = false;
// Скрываем перекрестие
if (crosshair) {
crosshair.style.display = "none";
}
// остановка stream
camImage.src = "";
rightPanel.classList.add("hidden");
if (btn) {
btn.querySelector('.cam-btn-text').textContent = 'Камера';
}
console.log("[camera] closed");
updateResizerVisibility();
// Останавливаем мониторинг
stopStreamMonitoring();
}
function toggle() {
if (isOpen) {
close();
} else {
open();
}
}
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 = 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 crosshair = document.getElementById("crosshair");
if (crosshair) {
crosshair.style.display = show ? "block" : "none";
}
}
export function setCrosshairOpacity(opacity) {
const crosshair = document.getElementById("crosshair");
if (crosshair) {
crosshair.style.opacity = opacity;
}
}