feat(面板): 实现浮动面板拖拽功能并优化样式
添加面板拖拽功能,允许用户通过标题栏拖动面板。重构面板样式,移除固定位置属性,改为居中显示并支持动态调整。同时添加语言面板状态管理,优化面板动画效果。
This commit is contained in:
@@ -121,9 +121,65 @@ const fullscreenState = {
|
|||||||
const panelState = {
|
const panelState = {
|
||||||
configPanel: false,
|
configPanel: false,
|
||||||
captionPanel: false,
|
captionPanel: false,
|
||||||
|
languagePanel: false,
|
||||||
logPanel: false
|
logPanel: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let panelDragState = {
|
||||||
|
isDragging: false,
|
||||||
|
currentPanel: null,
|
||||||
|
offsetX: 0,
|
||||||
|
offsetY: 0,
|
||||||
|
originalHeight: null
|
||||||
|
};
|
||||||
|
|
||||||
|
function initPanelDrag() {
|
||||||
|
document.querySelectorAll('.floating-panel').forEach(panel => {
|
||||||
|
const header = panel.querySelector('.panel-header');
|
||||||
|
if (!header) return;
|
||||||
|
|
||||||
|
header.style.cursor = 'move';
|
||||||
|
|
||||||
|
header.addEventListener('mousedown', (e) => {
|
||||||
|
if (e.target.tagName === 'BUTTON') return;
|
||||||
|
|
||||||
|
panelDragState.isDragging = true;
|
||||||
|
panelDragState.currentPanel = panel;
|
||||||
|
|
||||||
|
const rect = panel.getBoundingClientRect();
|
||||||
|
panelDragState.offsetX = e.clientX - rect.left;
|
||||||
|
panelDragState.offsetY = e.clientY - rect.top;
|
||||||
|
panelDragState.originalHeight = panel.offsetHeight;
|
||||||
|
|
||||||
|
panel.style.transform = 'none';
|
||||||
|
panel.style.height = panelDragState.originalHeight + 'px';
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('mousemove', (e) => {
|
||||||
|
if (!panelDragState.isDragging || !panelDragState.currentPanel) return;
|
||||||
|
|
||||||
|
const x = e.clientX - panelDragState.offsetX;
|
||||||
|
const y = e.clientY - panelDragState.offsetY;
|
||||||
|
|
||||||
|
const maxX = window.innerWidth - panelDragState.currentPanel.offsetWidth;
|
||||||
|
const maxY = window.innerHeight - panelDragState.currentPanel.offsetHeight;
|
||||||
|
|
||||||
|
panelDragState.currentPanel.style.left = Math.max(0, Math.min(x, maxX)) + 'px';
|
||||||
|
panelDragState.currentPanel.style.top = Math.max(0, Math.min(y, maxY)) + 'px';
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('mouseup', () => {
|
||||||
|
if (panelDragState.isDragging) {
|
||||||
|
panelDragState.isDragging = false;
|
||||||
|
if (panelDragState.currentPanel) {
|
||||||
|
panelDragState.currentPanel.style.height = '';
|
||||||
|
}
|
||||||
|
panelDragState.currentPanel = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const logger = {
|
const logger = {
|
||||||
log(level, message, data = null) {
|
log(level, message, data = null) {
|
||||||
const timestamp = new Date().toLocaleTimeString('zh-CN', { hour12: false });
|
const timestamp = new Date().toLocaleTimeString('zh-CN', { hour12: false });
|
||||||
@@ -1248,6 +1304,7 @@ function init() {
|
|||||||
bindEvents();
|
bindEvents();
|
||||||
updateUIState();
|
updateUIState();
|
||||||
initScaling();
|
initScaling();
|
||||||
|
initPanelDrag();
|
||||||
watchCaptionContainer();
|
watchCaptionContainer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -182,26 +182,28 @@ body {
|
|||||||
z-index: 999;
|
z-index: 999;
|
||||||
display: none;
|
display: none;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
max-height: 80vh;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
animation: panelSlideIn 0.2s ease-out;
|
animation: panelSlideIn 0.2s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.floating-panel.visible {
|
||||||
|
display: flex;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes panelSlideIn {
|
@keyframes panelSlideIn {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(10px);
|
transform: translate(-50%, -50%) translateY(10px);
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translate(-50%, -50%) translateY(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.floating-panel.visible {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-header {
|
.panel-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -246,10 +248,8 @@ body {
|
|||||||
|
|
||||||
/* ===== 连接配置面板 ===== */
|
/* ===== 连接配置面板 ===== */
|
||||||
.config-panel {
|
.config-panel {
|
||||||
bottom: calc(var(--spacing-xl) + 60px);
|
|
||||||
right: var(--spacing-xl);
|
right: var(--spacing-xl);
|
||||||
width: 360px;
|
width: 360px;
|
||||||
max-height: 70vh;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-section {
|
.config-section {
|
||||||
@@ -338,6 +338,7 @@ body {
|
|||||||
bottom: calc(var(--spacing-xl) + 60px);
|
bottom: calc(var(--spacing-xl) + 60px);
|
||||||
right: var(--spacing-xl);
|
right: var(--spacing-xl);
|
||||||
width: 320px;
|
width: 320px;
|
||||||
|
max-height: 90vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.caption-style-section {
|
.caption-style-section {
|
||||||
@@ -364,7 +365,6 @@ body {
|
|||||||
|
|
||||||
/* ===== 语言切换面板 ===== */
|
/* ===== 语言切换面板 ===== */
|
||||||
.language-panel {
|
.language-panel {
|
||||||
bottom: calc(var(--spacing-xl) + 60px);
|
|
||||||
right: var(--spacing-xl);
|
right: var(--spacing-xl);
|
||||||
width: 280px;
|
width: 280px;
|
||||||
}
|
}
|
||||||
@@ -408,10 +408,8 @@ body {
|
|||||||
|
|
||||||
/* ===== 日志面板 ===== */
|
/* ===== 日志面板 ===== */
|
||||||
.log-panel {
|
.log-panel {
|
||||||
bottom: calc(var(--spacing-xl) + 60px);
|
|
||||||
right: var(--spacing-xl);
|
right: var(--spacing-xl);
|
||||||
width: 450px;
|
width: 450px;
|
||||||
max-height: 60vh;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.log-toolbar {
|
.log-toolbar {
|
||||||
|
|||||||
Reference in New Issue
Block a user