регулировка ресайза
This commit is contained in:
@@ -166,7 +166,7 @@ h1 {
|
||||
|
||||
.fill {
|
||||
height: 100%;
|
||||
width: 0%;
|
||||
width: 0;
|
||||
background: #e6852d;
|
||||
box-shadow:
|
||||
inset 0 0 4px rgba(255,255,255,0.2),
|
||||
@@ -177,7 +177,7 @@ h1 {
|
||||
.fill.no-connection {
|
||||
background: #555555 !important;
|
||||
box-shadow: none !important;
|
||||
width: 0% !important;
|
||||
width: 0 !important;
|
||||
}
|
||||
|
||||
/* ===== SIGNAL ICON ===== */
|
||||
@@ -194,7 +194,7 @@ h1 {
|
||||
flex: 1;
|
||||
border-radius: 2px;
|
||||
min-width: 5px;
|
||||
border: 1.5px solid #e6852d;
|
||||
border: 2px solid #e6852d;
|
||||
background-color: transparent;
|
||||
transition: background-color 0.3s, border-color 0.3s;
|
||||
}
|
||||
|
||||
@@ -1,23 +1,18 @@
|
||||
// camera.ts
|
||||
import { updateResizerVisibility } from './layout.js';
|
||||
import { updateResizerVisibility, openRightPanel, closeRightPanel } from './layout.js';
|
||||
|
||||
let rightPanel: HTMLElement | null = null;
|
||||
let camImage: HTMLImageElement | null = null;
|
||||
let crosshair: HTMLElement | null = null;
|
||||
let isOpen: boolean = false;
|
||||
let streamCheckInterval: number | null = null;
|
||||
|
||||
interface StreamResponse {
|
||||
cam: string;
|
||||
available: boolean;
|
||||
source: string;
|
||||
}
|
||||
let resizer: HTMLElement | null = null;
|
||||
|
||||
export function initCamera(): void {
|
||||
rightPanel = document.getElementById("rightPanel");
|
||||
camImage = document.getElementById("camImage") as HTMLImageElement;
|
||||
crosshair = document.getElementById("crosshair");
|
||||
|
||||
resizer = document.getElementById("dragBar");
|
||||
|
||||
const btn = document.getElementById("camToggle");
|
||||
|
||||
@@ -28,9 +23,8 @@ export function initCamera(): void {
|
||||
|
||||
isOpen = true;
|
||||
|
||||
if (rightPanel) {
|
||||
rightPanel.classList.remove("hidden");
|
||||
}
|
||||
// Открываем правую панель через layout
|
||||
openRightPanel();
|
||||
|
||||
// Показываем перекрестие
|
||||
if (crosshair) {
|
||||
@@ -44,13 +38,15 @@ export function initCamera(): void {
|
||||
|
||||
if (btn) {
|
||||
const textSpan = btn.querySelector('.cam-btn-text');
|
||||
if (textSpan) textSpan.textContent = 'Скрыть';
|
||||
if (textSpan) {
|
||||
textSpan.textContent = 'Скрыть';
|
||||
} else {
|
||||
btn.innerHTML = '📷 Скрыть';
|
||||
}
|
||||
}
|
||||
|
||||
console.log("[camera] opened");
|
||||
|
||||
updateResizerVisibility();
|
||||
|
||||
// Запускаем мониторинг потока
|
||||
startStreamMonitoring();
|
||||
}
|
||||
@@ -65,24 +61,25 @@ export function initCamera(): void {
|
||||
crosshair.style.display = "none";
|
||||
}
|
||||
|
||||
// остановка stream
|
||||
// Останавливаем поток
|
||||
if (camImage) {
|
||||
camImage.src = "";
|
||||
}
|
||||
|
||||
if (rightPanel) {
|
||||
rightPanel.classList.add("hidden");
|
||||
}
|
||||
// Закрываем правую панель через layout
|
||||
closeRightPanel();
|
||||
|
||||
if (btn) {
|
||||
const textSpan = btn.querySelector('.cam-btn-text');
|
||||
if (textSpan) textSpan.textContent = 'Камера';
|
||||
if (textSpan) {
|
||||
textSpan.textContent = 'Камера';
|
||||
} else {
|
||||
btn.innerHTML = '📷 Камера';
|
||||
}
|
||||
}
|
||||
|
||||
console.log("[camera] closed");
|
||||
|
||||
updateResizerVisibility();
|
||||
|
||||
// Останавливаем мониторинг
|
||||
stopStreamMonitoring();
|
||||
}
|
||||
@@ -139,7 +136,15 @@ export function initCamera(): void {
|
||||
}
|
||||
}
|
||||
|
||||
// Экспортируем для возможности ручного управления
|
||||
// ============================================
|
||||
// ПУБЛИЧНЫЕ ФУНКЦИИ (используются в других модулях)
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* Показать/скрыть перекрестие на видео
|
||||
* @param show - показывать или скрыть
|
||||
*/
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
export function showCrosshair(show: boolean = true): void {
|
||||
const crosshairElem = document.getElementById("crosshair");
|
||||
if (crosshairElem) {
|
||||
@@ -147,9 +152,14 @@ export function showCrosshair(show: boolean = true): void {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Установить прозрачность перекрестия
|
||||
* @param opacity - значение прозрачности (0-1)
|
||||
*/
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
export function setCrosshairOpacity(opacity: string | number): void {
|
||||
const crosshairElem = document.getElementById("crosshair");
|
||||
if (crosshairElem) {
|
||||
crosshairElem.style.opacity = String(opacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,88 +1,236 @@
|
||||
// layout.ts
|
||||
let resizer: HTMLElement | null = null;
|
||||
let leftPanel: HTMLElement | null = null;
|
||||
let rightPanel: HTMLElement | null = null;
|
||||
let dragBar: HTMLElement | null = null;
|
||||
let isDragging: boolean = false;
|
||||
let pendingX: number | null = null;
|
||||
let isOpen: boolean = false;
|
||||
let lastLeftWidth: number = 0;
|
||||
let lastRightWidth: number = 0;
|
||||
|
||||
export function initResize(): void {
|
||||
resizer = document.getElementById("dragBar");
|
||||
leftPanel = document.getElementById("leftPanel");
|
||||
rightPanel = document.getElementById("rightPanel");
|
||||
dragBar = document.getElementById("dragBar");
|
||||
|
||||
if (!leftPanel || !rightPanel || !dragBar) return;
|
||||
|
||||
const savedRatio = localStorage.getItem('layoutRatio');
|
||||
if (savedRatio) {
|
||||
applyRatio(parseFloat(savedRatio));
|
||||
if (!resizer || !leftPanel || !rightPanel) {
|
||||
console.warn("[layout] Элементы не найдены");
|
||||
return;
|
||||
}
|
||||
|
||||
dragBar.addEventListener("mousedown", (e) => {
|
||||
if (rightPanel!.classList.contains("hidden")) return;
|
||||
// Проверяем видимость при инициализации
|
||||
updateResizerVisibility();
|
||||
|
||||
let isDragging = false;
|
||||
|
||||
// Обработчик начала перетаскивания
|
||||
resizer.addEventListener("mousedown", (e: MouseEvent) => {
|
||||
// Сохраняем ссылки на элементы в локальные переменные
|
||||
const left = leftPanel;
|
||||
const right = rightPanel;
|
||||
|
||||
// Проверяем, что элементы существуют
|
||||
if (!left || !right) {
|
||||
console.warn("[layout] Панели не найдены");
|
||||
return;
|
||||
}
|
||||
|
||||
// Проверяем, что правая панель видима
|
||||
if (right.classList.contains("hidden")) {
|
||||
return;
|
||||
}
|
||||
|
||||
isDragging = true;
|
||||
document.body.style.cursor = "col-resize";
|
||||
e.preventDefault();
|
||||
});
|
||||
document.body.style.userSelect = "none";
|
||||
|
||||
document.addEventListener("mouseup", () => {
|
||||
if (!isDragging) return;
|
||||
// Сохраняем начальные размеры
|
||||
const startX = e.clientX;
|
||||
const leftWidth = left.getBoundingClientRect().width;
|
||||
const rightWidth = right.getBoundingClientRect().width;
|
||||
const totalWidth = leftWidth + rightWidth;
|
||||
|
||||
isDragging = false;
|
||||
document.body.style.cursor = "default";
|
||||
function onMouseMove(moveEvent: MouseEvent): void {
|
||||
if (!isDragging) return;
|
||||
|
||||
if (rightPanel && !rightPanel.classList.contains("hidden")) {
|
||||
const total = window.innerWidth;
|
||||
const leftWidth = leftPanel!.getBoundingClientRect().width;
|
||||
localStorage.setItem('layoutRatio', String(leftWidth / total));
|
||||
// Проверяем, что элементы всё ещё существуют
|
||||
if (!left || !right) return;
|
||||
|
||||
const deltaX = moveEvent.clientX - startX;
|
||||
let newLeftWidth = leftWidth + deltaX;
|
||||
|
||||
// Ограничиваем минимальные размеры
|
||||
const minWidth = 200;
|
||||
newLeftWidth = Math.max(minWidth, Math.min(totalWidth - minWidth, newLeftWidth));
|
||||
|
||||
const newRightWidth = totalWidth - newLeftWidth;
|
||||
|
||||
left.style.flex = `0 0 ${newLeftWidth}px`;
|
||||
right.style.flex = `0 0 ${newRightWidth}px`;
|
||||
|
||||
// Сохраняем последние размеры
|
||||
lastLeftWidth = newLeftWidth;
|
||||
lastRightWidth = newRightWidth;
|
||||
}
|
||||
|
||||
function onMouseUp(): void {
|
||||
isDragging = false;
|
||||
document.body.style.cursor = "";
|
||||
document.body.style.userSelect = "";
|
||||
|
||||
document.removeEventListener("mousemove", onMouseMove);
|
||||
document.removeEventListener("mouseup", onMouseUp);
|
||||
}
|
||||
|
||||
document.addEventListener("mousemove", onMouseMove);
|
||||
document.addEventListener("mouseup", onMouseUp);
|
||||
});
|
||||
|
||||
document.addEventListener("mousemove", (e) => {
|
||||
if (!isDragging) return;
|
||||
if (rightPanel && rightPanel.classList.contains("hidden")) return;
|
||||
|
||||
pendingX = e.clientX;
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
if (pendingX === null) return;
|
||||
if (!leftPanel || !rightPanel || !dragBar) return;
|
||||
|
||||
const total = window.innerWidth;
|
||||
let leftWidth = pendingX;
|
||||
|
||||
const min = 300;
|
||||
if (leftWidth < min) leftWidth = min;
|
||||
if (leftWidth > total - min) leftWidth = total - min;
|
||||
|
||||
const rightWidth = total - leftWidth - dragBar.offsetWidth;
|
||||
|
||||
leftPanel.style.flex = `0 0 ${leftWidth}px`;
|
||||
rightPanel.style.flex = `0 0 ${rightWidth}px`;
|
||||
|
||||
pendingX = null;
|
||||
});
|
||||
// Обработчик изменения размера окна
|
||||
window.addEventListener("resize", () => {
|
||||
handleWindowResize();
|
||||
});
|
||||
}
|
||||
|
||||
function applyRatio(ratio: number): void {
|
||||
const total = window.innerWidth;
|
||||
const leftWidth = Math.floor(total * ratio);
|
||||
const rightWidth = total - leftWidth;
|
||||
/**
|
||||
* Обработка изменения размера окна
|
||||
*/
|
||||
function handleWindowResize(): void {
|
||||
if (!leftPanel || !rightPanel) return;
|
||||
|
||||
if (leftPanel && rightPanel) {
|
||||
leftPanel.style.flex = `0 0 ${leftWidth}px`;
|
||||
rightPanel.style.flex = `0 0 ${rightWidth}px`;
|
||||
// Если правая панель видима, пересчитываем размеры
|
||||
if (!rightPanel.classList.contains("hidden")) {
|
||||
// Если есть сохраненные размеры, используем их пропорционально
|
||||
if (lastLeftWidth > 0 && lastRightWidth > 0) {
|
||||
const totalWidth = window.innerWidth;
|
||||
const ratio = lastLeftWidth / (lastLeftWidth + lastRightWidth);
|
||||
const newLeftWidth = totalWidth * ratio;
|
||||
const newRightWidth = totalWidth - newLeftWidth;
|
||||
|
||||
// Ограничиваем минимальные размеры
|
||||
const minWidth = 200;
|
||||
const finalLeftWidth = Math.max(minWidth, Math.min(totalWidth - minWidth, newLeftWidth));
|
||||
const finalRightWidth = totalWidth - finalLeftWidth;
|
||||
|
||||
leftPanel.style.flex = `0 0 ${finalLeftWidth}px`;
|
||||
rightPanel.style.flex = `0 0 ${finalRightWidth}px`;
|
||||
|
||||
lastLeftWidth = finalLeftWidth;
|
||||
lastRightWidth = finalRightWidth;
|
||||
} else {
|
||||
// Если нет сохраненных размеров, делим пополам
|
||||
const totalWidth = window.innerWidth;
|
||||
const halfWidth = totalWidth / 2;
|
||||
leftPanel.style.flex = `0 0 ${halfWidth}px`;
|
||||
rightPanel.style.flex = `0 0 ${halfWidth}px`;
|
||||
|
||||
lastLeftWidth = halfWidth;
|
||||
lastRightWidth = halfWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Обновление видимости разделителя в зависимости от состояния правой панели
|
||||
*/
|
||||
export function updateResizerVisibility(): void {
|
||||
if (!dragBar || !rightPanel || !leftPanel) return;
|
||||
if (!resizer || !rightPanel) return;
|
||||
|
||||
// Если правая панель скрыта - скрываем разделитель
|
||||
if (rightPanel.classList.contains("hidden")) {
|
||||
resizer.classList.add("hidden");
|
||||
} else {
|
||||
resizer.classList.remove("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Открыть правую панель
|
||||
*/
|
||||
export function openRightPanel(): void {
|
||||
if (!leftPanel || !rightPanel) return;
|
||||
|
||||
// Убираем класс hidden
|
||||
rightPanel.classList.remove("hidden");
|
||||
|
||||
// Обновляем разделитель
|
||||
updateResizerVisibility();
|
||||
|
||||
// Устанавливаем размеры
|
||||
const totalWidth = window.innerWidth;
|
||||
const halfWidth = totalWidth / 2;
|
||||
|
||||
// Проверяем, есть ли сохраненные размеры
|
||||
if (lastLeftWidth > 0 && lastRightWidth > 0) {
|
||||
// Используем сохраненные пропорции
|
||||
const ratio = lastLeftWidth / (lastLeftWidth + lastRightWidth);
|
||||
const newLeftWidth = totalWidth * ratio;
|
||||
const newRightWidth = totalWidth - newLeftWidth;
|
||||
|
||||
const minWidth = 200;
|
||||
const finalLeftWidth = Math.max(minWidth, Math.min(totalWidth - minWidth, newLeftWidth));
|
||||
const finalRightWidth = totalWidth - finalLeftWidth;
|
||||
|
||||
leftPanel.style.flex = `0 0 ${finalLeftWidth}px`;
|
||||
rightPanel.style.flex = `0 0 ${finalRightWidth}px`;
|
||||
|
||||
lastLeftWidth = finalLeftWidth;
|
||||
lastRightWidth = finalRightWidth;
|
||||
} else {
|
||||
// Делим пополам
|
||||
leftPanel.style.flex = `0 0 ${halfWidth}px`;
|
||||
rightPanel.style.flex = `0 0 ${halfWidth}px`;
|
||||
|
||||
lastLeftWidth = halfWidth;
|
||||
lastRightWidth = halfWidth;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Закрыть правую панель
|
||||
*/
|
||||
export function closeRightPanel(): void {
|
||||
if (!rightPanel) return;
|
||||
|
||||
// Добавляем класс hidden
|
||||
rightPanel.classList.add("hidden");
|
||||
|
||||
// Обновляем разделитель
|
||||
updateResizerVisibility();
|
||||
|
||||
// Сбрасываем flex для левой панели
|
||||
if (leftPanel) {
|
||||
leftPanel.style.flex = "1 1 auto";
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// ПУБЛИЧНЫЕ ФУНКЦИИ (используются в других модулях)
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* Установить видимость разделителя вручную
|
||||
* @param visible - показывать или скрыть
|
||||
*/
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
export function setResizerVisible(visible: boolean): void {
|
||||
if (resizer) {
|
||||
if (visible) {
|
||||
resizer.classList.remove("hidden");
|
||||
} else {
|
||||
resizer.classList.add("hidden");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Переключить состояние правой панели
|
||||
*/
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
export function toggleRightPanel(): void {
|
||||
if (!rightPanel) return;
|
||||
|
||||
if (rightPanel.classList.contains("hidden")) {
|
||||
dragBar.classList.add("hidden");
|
||||
leftPanel.style.flex = "1";
|
||||
openRightPanel();
|
||||
} else {
|
||||
dragBar.classList.remove("hidden");
|
||||
closeRightPanel();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user