commit 172f978edf9c1f8e0ec493d55c4038a54e031901 Author: ElmGates <396832647@qq.com> Date: Sat Dec 27 13:07:25 2025 +0800 upload diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/index.html b/index.html new file mode 100644 index 0000000..b259f08 --- /dev/null +++ b/index.html @@ -0,0 +1,169 @@ + + +
+ + +
+ © 2025-Now SuperJia
All Rights Reserved
版本 v1.5, 发布于2025-12
+
请输入您的提词内容,然后点击"格式化文本"按钮开始使用...
+上传PDF文件,自动生成镜像提词效果
+点击或拖拽PDF文件到此处
+ +${sentence}
`; + }); + + if (html === '') { + html = '请输入您的提词内容,然后点击"格式化文本"按钮开始使用...
'; + } + + this.textDisplay.innerHTML = html; + this.totalLinesSpan.textContent = this.totalLines; + + // 应用当前的行间距设置 + const currentLineHeight = this.lineHeight.value; + const paragraphs = this.textDisplay.querySelectorAll('p'); + paragraphs.forEach(p => { + p.style.lineHeight = currentLineHeight; + }); + + // 计算每行的高度并存储 + paragraphs.forEach((p, index) => { + const height = p.offsetHeight + parseFloat(getComputedStyle(p).marginBottom); + this.lineHeights[index] = height; + }); + + // 计算初始位置,将第一行文本对齐到中间位置 + const containerHeight = this.teleprompterContent.clientHeight; + const firstLineHeight = this.lineHeights[0] || this.getCurrentLineHeight(); + const totalContentHeight = this.lineHeights.reduce((sum, height) => sum + height, 0); + + // 如果内容高度小于容器高度,将第一行放在中间位置 + // 如果内容高度大于容器高度,确保第一行不会被遮挡 + let startPosition = (containerHeight / 2) - firstLineHeight; + + // 确保起始位置不会导致文本显示在容器底部之外 + if (startPosition < 0) { + startPosition = Math.min(50, containerHeight / 4); // 给一个合理的顶部边距 + } + + // 重置滚动位置 + this.currentPosition = 0; + const isMirror = this.mirrorText.checked; + const mirrorScale = isMirror ? ' scaleX(-1)' : ' scaleX(1)'; + this.textDisplay.style.transform = `translateY(${startPosition}px)${mirrorScale}`; + } + + // 滚动功能 + startScrolling() { + this.notifyRemote('control', { action: 'start' }); + if (this.formattedText.length === 0) { + alert('请先格式化文本!'); + return; + } + + if (this.isPaused) { + this.resumeScrolling(); + return; + } + + this.isScrolling = true; + this.isPaused = false; + this.startScrollBtn.textContent = '滚动中...'; + this.startScrollBtn.disabled = true; + this.readingGuide.classList.add('visible'); + + const speed = parseFloat(this.scrollSpeed.value); + const interval = Math.max(20, 210 - speed); // 扩大速度转换范围,最低20ms,最高190ms + + this.scrollInterval = setInterval(() => { + this.scrollStep(); + }, interval); + } + + scrollStep() { + if (this.formattedText.length === 0) { + this.stopScrolling(); + alert('请先格式化文本!'); + return; + } + + const lineHeight = this.getCurrentLineHeight(); + this.currentPosition += 1; + + // 更新当前行 + let accumulatedHeight = 0; + let newLine = 0; + for (let i = 0; i < this.lineHeights.length; i++) { + accumulatedHeight += this.lineHeights[i]; + if (accumulatedHeight > this.currentPosition) { + newLine = i; + break; + } + newLine = i; + } + + if (newLine !== this.currentLine && newLine < this.totalLines) { + this.currentLine = newLine; + this.updateProgress(); + } + + // 应用滚动 + const isMirror = this.mirrorText.checked; + const mirrorScale = isMirror ? ' scaleX(-1)' : ' scaleX(1)'; + this.textDisplay.style.transform = `translateY(-${this.currentPosition}px)${mirrorScale}`; + + // 检查是否滚动到底部 + const containerHeight = this.teleprompterContent.clientHeight; + const contentHeight = this.textDisplay.scrollHeight; + + if (this.currentPosition + containerHeight >= contentHeight) { + this.stopScrolling(); + alert('已滚动到文本末尾!'); + } + } + + pauseScrolling() { + if (this.isScrolling && !this.isPaused) { + this.notifyRemote('control', { action: 'pause' }); + this.isPaused = true; + clearInterval(this.scrollInterval); + this.pauseScrollBtn.textContent = '继续'; + this.startScrollBtn.textContent = '继续'; + this.startScrollBtn.disabled = false; + } + } + + resumeScrolling() { + if (this.isPaused) { + this.isPaused = false; + this.startScrolling(); + this.pauseScrollBtn.textContent = '暂停'; + } + } + + resetScrolling() { + this.stopScrolling(); + this.currentPosition = 0; + this.currentLine = 0; + + // 重置到初始中间位置 + const containerHeight = this.teleprompterContent.clientHeight; + const firstLineHeight = this.lineHeights[0] || this.getCurrentLineHeight(); + let startPosition = (containerHeight / 2) - firstLineHeight; + + // 确保起始位置不会导致文本显示在容器底部之外 + if (startPosition < 0) { + startPosition = Math.min(50, containerHeight / 4); // 给一个合理的顶部边距 + } + + const isMirror = this.mirrorText.checked; + const mirrorScale = isMirror ? ' scaleX(-1)' : ' scaleX(1)'; + this.textDisplay.style.transform = `translateY(${startPosition}px)${mirrorScale}`; + + this.updateProgress(); + this.readingGuide.classList.remove('visible'); + } + + stopScrolling() { + this.isScrolling = false; + this.isPaused = false; + clearInterval(this.scrollInterval); + this.startScrollBtn.textContent = '开始'; + this.startScrollBtn.disabled = false; + this.pauseScrollBtn.textContent = '暂停'; + } + + // 显示设置 + updateFontSize() { + const size = this.fontSize.value; + this.fontSizeValue.textContent = size + 'px'; + this.textDisplay.style.fontSize = size + 'px'; + + // 重新计算行高 + if (this.formattedText.length > 0) { + setTimeout(() => this.displayFormattedText(), 50); + } + this.saveSettings(); + } + + updateLineHeight() { + const height = this.lineHeight.value; + this.lineHeightValue.textContent = height; + + // 应用到所有段落,让每一行都有这个行间距 + const paragraphs = this.textDisplay.querySelectorAll('p'); + paragraphs.forEach(p => { + p.style.lineHeight = height; + }); + + // 重新计算行高 + if (this.formattedText.length > 0) { + setTimeout(() => this.displayFormattedText(), 50); + } + this.saveSettings(); + } + + updateTextColor() { + const color = this.textColor.value; + this.textDisplay.style.color = color; + this.saveSettings(); + } + + updateBgColor() { + const color = this.bgColor.value; + this.teleprompterContainer.style.backgroundColor = color; + this.saveSettings(); + } + + updateMirrorText() { + const text = this.textInput.value.trim(); + if (text === '') { + this.textDisplay.innerHTML = ''; + this.formattedText = []; + return; + } + + // 简单按换行符分段,保持原始段落结构 + const lines = text.split('\n').map(line => line.trim()).filter(line => line !== ''); + this.formattedText = lines; + this.totalLines = lines.length; + const formattedText = lines.map(line => `${line}
`).join(''); + + this.textDisplay.innerHTML = formattedText; + + // 应用当前设置 + this.updateFontSize(); + this.updateLineHeight(); + this.updateTextColor(); + this.updateBgColor(); + + // 更新镜像状态 + const isMirror = this.mirrorText.checked; + if (isMirror) { + this.textDisplay.style.transform = `translateY(-${this.currentPosition}px) scaleX(-1)`; + } else { + this.textDisplay.style.transform = `translateY(-${this.currentPosition}px) scaleX(1)`; + } + + this.saveSettings(); + } + + // 高级功能 + toggleAdvancedMenu() { + const isVisible = this.advancedContent.style.display === 'block'; + this.advancedContent.style.display = isVisible ? 'none' : 'block'; + this.advancedToggle.style.transform = isVisible ? 'rotate(0deg)' : 'rotate(180deg)'; + } + + updateMaxWordsPerParagraph() { + const value = this.maxWordsPerParagraph.value; + this.maxWordsValue.textContent = value; + this.saveSettings(); + } + + updateForceParagraphBreak() { + this.saveSettings(); + } + + + + // 全屏功能 + toggleFullscreen() { + if (!document.fullscreenElement) { + this.container.requestFullscreen().then(() => { + this.container.classList.add('fullscreen'); + this.toggleFullscreenBtn.textContent = '退出全屏'; + }).catch(err => { + alert(`无法进入全屏模式: ${err.message}`); + }); + } else { + document.exitFullscreen().then(() => { + this.container.classList.remove('fullscreen'); + this.toggleFullscreenBtn.textContent = '全屏显示'; + }); + } + } + + togglePanel() { + this.controlPanel.classList.toggle('hidden'); + const isHidden = this.controlPanel.classList.contains('hidden'); + this.togglePanelBtn.textContent = isHidden ? '显示控制面板' : '隐藏控制面板'; + this.showPanelBtn.style.display = isHidden ? 'block' : 'none'; + + // 同时切换容器的panel-hidden类,用于扩展文本显示区域 + this.container.classList.toggle('panel-hidden', isHidden); + + // 切换body的背景样式,隐藏蓝色渐变背景 + document.body.classList.toggle('panel-hidden-bg', isHidden); + } + + // 键盘快捷键 + handleKeyboard(e) { + if (e.target.tagName === 'TEXTAREA') return; + + switch(e.key) { + case ' ': + e.preventDefault(); + if (this.isScrolling && !this.isPaused) { + this.pauseScrolling(); + } else { + this.startScrolling(); + } + break; + case 'r': + case 'R': + this.resetScrolling(); + break; + case 'f': + case 'F': + this.toggleFullscreen(); + break; + case 'Escape': + if (document.fullscreenElement) { + this.toggleFullscreen(); + } + break; + } + } + + // 快速定位功能 + jumpToLine() { + if (!this.formattedText || this.formattedText.length === 0) { + alert('请先格式化文本'); + return; + } + + const targetLine = parseInt(this.jumpToLineInput.value); + if (isNaN(targetLine) || targetLine < 1 || targetLine > this.formattedText.length) { + alert(`请输入有效的行号 (1-${this.formattedText.length})`); + return; + } + + this.jumpToLineByIndex(targetLine - 1); + this.notifyRemote('jump', { index: targetLine - 1 }); + } + + notifyRemote(type, payload) { + if (this.remoteController && !this.remoteController.isProcessingRemote) { + this.remoteController.sendData(type, payload); + } + } + + prevLine() { + if (!this.formattedText || this.formattedText.length === 0) return; + this.jumpToLineByIndex(this.currentLine - 1); + this.notifyRemote('control', { action: 'prevLine' }); + } + + nextLine() { + if (!this.formattedText || this.formattedText.length === 0) return; + this.jumpToLineByIndex(this.currentLine + 1); + this.notifyRemote('control', { action: 'nextLine' }); + } + + jumpToLineByIndex(index) { + if (index < 0) index = 0; + if (index >= this.totalLines) index = this.totalLines - 1; + + this.stopScrolling(); + this.currentLine = index; + this.currentPosition = this.calculatePositionForLine(this.currentLine); + + const isMirror = this.mirrorText.checked; + const mirrorScale = isMirror ? ' scaleX(-1)' : ' scaleX(1)'; + this.textDisplay.style.transform = `translateY(-${this.currentPosition}px)${mirrorScale}`; + + this.updateProgress(); + } + + calculatePositionForLine(lineIndex) { + let position = 0; + for (let i = 0; i < lineIndex && i < this.lineHeights.length; i++) { + position += this.lineHeights[i] || this.getCurrentLineHeight(); + } + return position; + } + + // 进度更新 + updateProgress() { + const progress = this.totalLines > 0 ? (this.currentLine / this.totalLines) * 100 : 0; + this.progressFill.style.width = progress + '%'; + this.currentLineSpan.textContent = this.currentLine + 1; + } + + // 工具方法 + getCurrentLineHeight() { + const firstParagraph = this.textDisplay.querySelector('p'); + if (firstParagraph) { + return firstParagraph.offsetHeight + + parseFloat(getComputedStyle(firstParagraph).marginBottom); + } + return 50; // 默认值 + } + + handleResize() { + // 重新计算行高和位置 + if (this.formattedText.length > 0) { + this.displayFormattedText(); + } else { + // 如果没有格式化文本,重新初始化位置 + this.initializeTextPosition(); + } + } + + handleFullscreenChange() { + if (!document.fullscreenElement) { + this.container.classList.remove('fullscreen'); + this.toggleFullscreenBtn.textContent = '全屏显示'; + } + } + + // 设置保存和加载 + saveSettings() { + const settings = { + scrollSpeed: this.scrollSpeed.value, + fontSize: this.fontSize.value, + lineHeight: this.lineHeight.value, + textColor: this.textColor.value, + bgColor: this.bgColor.value, + mirrorText: this.mirrorText.checked, + maxWordsPerParagraph: this.maxWordsPerParagraph.value, + forceParagraphBreak: this.forceParagraphBreak.checked + }; + localStorage.setItem('teleprompterSettings', JSON.stringify(settings)); + } + + loadSettings() { + // 加载设置 + const settings = localStorage.getItem('teleprompterSettings'); + if (settings) { + const parsed = JSON.parse(settings); + this.scrollSpeed.value = parsed.scrollSpeed || 50; + this.fontSize.value = parsed.fontSize || 32; + this.lineHeight.value = parsed.lineHeight || 1.8; + this.textColor.value = parsed.textColor || '#ffffff'; + this.bgColor.value = parsed.bgColor || '#000000'; + this.mirrorText.checked = parsed.mirrorText || false; + this.maxWordsPerParagraph.value = parsed.maxWordsPerParagraph || 50; + this.forceParagraphBreak.checked = parsed.forceParagraphBreak !== undefined ? parsed.forceParagraphBreak : true; + + // 应用设置 + this.speedValue.textContent = parseFloat(this.scrollSpeed.value).toFixed(1); + this.updateFontSize(); + this.updateLineHeight(); + this.updateTextColor(); + this.updateBgColor(); + this.updateMirrorText(); + this.updateMaxWordsPerParagraph(); + this.updateForceParagraphBreak(); + } + + // 加载文本 + const savedText = localStorage.getItem('teleprompterText'); + if (savedText) { + this.textInput.value = savedText; + setTimeout(() => this.formatText(), 100); + } + } +} + +// 初始化应用 +document.addEventListener('DOMContentLoaded', () => { + new Teleprompter(); +}); + +// 添加一些提示信息 +window.addEventListener('load', () => { + setTimeout(() => { + console.log('提词器应用已加载完成!'); + console.log('快捷键说明:'); + console.log('- 空格键:开始/暂停滚动'); + console.log('- R键:重置滚动'); + console.log('- F键:切换全屏'); + console.log('- ESC键:退出全屏'); + }, 1000); +}); \ No newline at end of file diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..f89c10b --- /dev/null +++ b/styles.css @@ -0,0 +1,573 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Microsoft YaHei', 'PingFang SC', 'Helvetica Neue', Arial, sans-serif; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + height: 100vh; + overflow: hidden; +} + +.container { + display: flex; + height: 100vh; + position: relative; +} + +/* 控制面板样式 */ + .control-panel { + width: 320px; + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); + border-right: 1px solid rgba(255, 255, 255, 0.2); + padding: 20px; + overflow-y: auto; + transition: transform 0.3s ease; + box-shadow: 2px 0 20px rgba(0, 0, 0, 0.1); + position: relative; + z-index: 1000; + } + + .control-panel.hidden { + transform: translateX(-100%); + } + + .control-panel.hidden + .teleprompter-container { + margin-left: 0; + } + + .teleprompter-container { + transition: margin-left 0.3s ease; + } + +.panel-section { + margin-bottom: 25px; + padding: 15px; + background: rgba(255, 255, 255, 0.8); + border-radius: 10px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); +} + +/* 版权信息样式 */ +.copyright-section { + margin-top: 20px; + padding: 15px 0 5px 0; + background: rgba(255, 255, 255, 0.6); + border-radius: 8px; + border-top: 2px solid rgba(102, 126, 234, 0.3); +} + +.copyright-section p { + margin: 0; + text-align: center; + font-size: 12px; + color: #666; + font-weight: 500; + letter-spacing: 0.5px; +} + +.panel-section h3 { + color: #333; + margin-bottom: 15px; + font-size: 16px; + font-weight: 600; + border-bottom: 2px solid #667eea; + padding-bottom: 5px; +} + +/* 文本输入区域 */ +#textInput { + width: 100%; + padding: 12px; + border: 2px solid #e1e5e9; + border-radius: 8px; + font-size: 14px; + resize: vertical; + min-height: 120px; + font-family: inherit; + transition: border-color 0.3s ease; +} + +#textInput:focus { + outline: none; + border-color: #667eea; + box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); +} + +/* 控制组 */ +.control-group { + margin-bottom: 15px; + display: flex; + align-items: center; + gap: 8px; + flex-wrap: nowrap; /* 防止换行 */ +} + +.control-group label { + font-weight: 500; + color: #555; + min-width: 60px; + font-size: 13px; + flex-shrink: 0; /* 防止标签收缩 */ +} + +.control-group input[type="range"] { + flex: 1; + min-width: 0; /* 允许滑块收缩 */ + height: 6px; + border-radius: 3px; + background: #ddd; + outline: none; + -webkit-appearance: none; +} + +.control-group input[type="range"]::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 18px; + height: 18px; + border-radius: 50%; + background: #667eea; + cursor: pointer; + transition: background 0.3s ease; +} + +.control-group input[type="range"]::-webkit-slider-thumb:hover { + background: #5a6fd8; +} + +.control-group input[type="color"] { + width: 50px; + height: 30px; + border: none; + border-radius: 5px; + cursor: pointer; +} + +.control-group input[type="checkbox"] { + width: 18px; + height: 18px; + cursor: pointer; + accent-color: #667eea; +} + +.control-group span { + font-weight: 600; + color: #667eea; + min-width: 35px; + max-width: 40px; /* 限制最大宽度 */ + text-align: center; + font-size: 12px; + flex-shrink: 0; /* 防止数字显示收缩 */ +} + +/* 按钮样式 */ +button { + padding: 10px 16px; + border: none; + border-radius: 8px; + font-size: 14px; + font-weight: 500; + cursor: pointer; + transition: all 0.3s ease; + margin: 5px; +} + +#formatText { + background: #28a745; + color: white; + width: 100%; + margin-top: 10px; +} + +#formatText:hover { + background: #218838; + transform: translateY(-1px); +} + +.control-buttons { + display: flex; + gap: 10px; + justify-content: center; +} + +#startScroll { + background: #007bff; + color: white; +} + +#startScroll:hover { + background: #0056b3; +} + +#pauseScroll { + background: #ffc107; + color: #212529; +} + +#pauseScroll:hover { + background: #e0a800; +} + +#resetScroll { + background: #dc3545; + color: white; +} + +#resetScroll:hover { + background: #c82333; +} + +#prevLineBtn, #nextLineBtn { + background: #6c757d; + color: white; + flex: 1; +} + +#prevLineBtn:hover, #nextLineBtn:hover { + background: #5a6268; +} + +#createRoomBtn { + background: #28a745; + color: white; +} +#createRoomBtn:hover { + background: #218838; +} + +#joinRoomBtn { + background: #007bff; + color: white; +} +#joinRoomBtn:hover { + background: #0056b3; +} + +#copyRoomIdBtn { + background: #e9ecef; + color: #333; + border: 1px solid #ced4da; + padding: 2px 8px; + margin: 0; +} +#copyRoomIdBtn:hover { + background: #dae0e5; +} + +#toggleFullscreen { + background: #6f42c1; + color: white; + width: 100%; + margin-bottom: 10px; +} + +#toggleFullscreen:hover { + background: #5a32a3; +} + +#togglePanel { + background: #17a2b8; + color: white; + width: 100%; +} + +#togglePanel:hover { + background: #138496; +} + +/* 进度条 */ +.progress-bar { + width: 100%; + height: 8px; + background: #e9ecef; + border-radius: 4px; + overflow: hidden; + margin-bottom: 10px; +} + +.progress-fill { + height: 100%; + background: linear-gradient(90deg, #667eea, #764ba2); + width: 0%; + transition: width 0.3s ease; +} + +.progress-text { + text-align: center; + font-weight: 600; + color: #667eea; + font-size: 14px; +} + +/* 提词器显示区域 */ +.teleprompter-container { + flex: 1; + background: #000; + position: relative; + overflow: hidden; + display: flex; + align-items: center; + justify-content: center; + transition: margin-left 0.3s ease; + min-height: 0; /* 修复flex项目的高度问题 */ +} + +/* 悬浮恢复按钮 */ +.show-panel-btn { + position: absolute; + top: 20px; + left: 20px; + background: rgba(23, 162, 184, 0.9); + color: white; + border: none; + padding: 10px 15px; + border-radius: 8px; + cursor: pointer; + font-size: 14px; + z-index: 1001; + transition: all 0.3s ease; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3); +} + +.show-panel-btn:hover { + background: rgba(23, 162, 184, 1); + transform: translateY(-2px); + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.4); +} + +.teleprompter-content { + width: 98%; + max-width: 1400px; + height: 85vh; + position: relative; + overflow: hidden; + transition: width 0.3s ease, max-width 0.3s ease; /* 添加过渡效果 */ +} + +/* 控制面板隐藏时扩展文本内容区域 */ +.container.panel-hidden .teleprompter-content { + width: 100%; /* 占满整个可用宽度 */ + max-width: none; /* 移除最大宽度限制 */ + height: 100vh; /* 占满整个视口高度 */ + margin: 0; /* 移除边距 */ + padding: 0 40px; /* 添加一些内边距,让文本不会太靠边 */ +} + +.text-display { + padding: 50px 20px; + transition: transform 0.1s linear; + will-change: transform; + color: #ffffff; /* 确保文本颜色为白色 */ + font-size: 32px; /* 默认字体大小 */ + line-height: 1.8; /* 默认行高 */ + font-weight: 500; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5); +} + +/* 控制面板隐藏时调整文本显示的内边距 */ +.container.panel-hidden .text-display { + padding: 50px 60px; /* 增加左右内边距,充分利用屏幕宽度 */ +} + +/* 全屏模式下的文本显示内边距 */ +.container.fullscreen .text-display { + padding: 50px 60px; /* 增加左右内边距,充分利用屏幕宽度 */ +} + +.text-display p { + margin-bottom: 0.5em; /* 减少段间距 */ + line-height: 1.8; /* 应用到每一行 */ + text-align: center; + font-weight: 400; + letter-spacing: 0.5px; + transition: all 0.3s ease; +} + +/* 阅读指导线 */ + .reading-guide { + position: absolute; + top: 50%; + left: 0; + right: 0; + height: 3px; + background: rgba(255, 255, 255, 0.8); + transform: translateY(-50%); + pointer-events: none; + opacity: 0; + transition: opacity 0.3s ease; + display: none; /* 隐藏阅读指导线 */ + } + +.reading-guide::before { + content: ''; + position: absolute; + top: -10px; + left: 0; + right: 0; + height: 20px; + background: linear-gradient( + 90deg, + transparent 0%, + rgba(255, 255, 255, 0.3) 20%, + rgba(255, 255, 255, 0.8) 50%, + rgba(255, 255, 255, 0.3) 80%, + transparent 100% + ); +} + +.reading-guide.visible { + opacity: 1; +} + +/* 全屏模式 */ +.container.fullscreen .control-panel { + display: none; +} + +.container.fullscreen .teleprompter-container { + width: 100vw; + height: 100vh; +} + +.container.fullscreen .teleprompter-content { + width: 100%; + max-width: none; + height: 100vh; + padding: 0 40px; /* 添加一些内边距,让文本不会太靠边 */ +} + +/* 控制面板隐藏时的全屏扩展 */ +.container.panel-hidden .teleprompter-container { + margin-left: 0; + width: 100vw; /* 使用视口宽度,占满整个屏幕 */ + border-radius: 0; + position: absolute; /* 使用绝对定位占满空间 */ + left: 0; + top: 0; + height: 100vh; /* 占满整个视口高度 */ +} + +.container.panel-hidden { + padding: 0; + border-radius: 0; + overflow: hidden; /* 防止出现滚动条 */ +} + +/* 当控制面板隐藏时,移除body的渐变背景 */ +body.panel-hidden-bg { + background: #000000; /* 纯黑色背景 */ +} + +/* 响应式设计 */ +@media (max-width: 768px) { + .control-panel { + width: 280px; + padding: 15px; + } + + .teleprompter-content { + width: 98%; + max-width: none; + } + + .text-display { + padding: 30px 15px; + } +} + +@media (min-width: 1200px) { + .teleprompter-content { + width: 95%; + max-width: 1600px; + } +} + +/* 动画效果 */ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.panel-section { + animation: fadeIn 0.5s ease forwards; +} + +.panel-section:nth-child(1) { animation-delay: 0.1s; } +.panel-section:nth-child(2) { animation-delay: 0.2s; } +.panel-section:nth-child(3) { animation-delay: 0.3s; } +.panel-section:nth-child(4) { animation-delay: 0.4s; } +.panel-section:nth-child(5) { animation-delay: 0.5s; } + +/* 模态框样式 */ +.modal-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + z-index: 2000; + backdrop-filter: blur(5px); + animation: fadeIn 0.3s ease; +} + +.modal-content { + background: white; + padding: 25px; + border-radius: 12px; + width: 85%; + max-width: 320px; + text-align: center; + box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2); + transform: translateY(0); + animation: slideUp 0.3s ease; +} + +.modal-content h3 { + color: #333; + margin-bottom: 15px; + font-size: 18px; +} + +.modal-content p { + color: #555; + margin-bottom: 10px; + line-height: 1.5; +} + +.modal-content button { + margin-top: 15px; + width: 100%; + background: #667eea; + color: white; + padding: 12px; + font-size: 15px; +} + +.modal-content button:hover { + background: #5a6fd8; +} + +@keyframes slideUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} \ No newline at end of file