feat(ui): add floating menu for video selection
Implement floating button that toggles a menu with video options Add styling for floating elements and handle click interactions Update video switching logic to prevent unintended transitions
This commit is contained in:
+12
@@ -43,6 +43,18 @@
|
||||
<p id="transcript"></p>
|
||||
</div>
|
||||
|
||||
<!-- 悬浮球 -->
|
||||
<div id="floating-button">
|
||||
<i class="fas fa-bars"></i>
|
||||
</div>
|
||||
|
||||
<!-- 悬浮菜单 -->
|
||||
<div id="menu-container" class="hidden">
|
||||
<button class="menu-item" data-video="视频资源/jimeng-2025-07-16-4437-比耶,然后微笑着优雅的左右摇晃.mp4">Pose</button>
|
||||
<button class="menu-item" data-video="视频资源/生成加油视频.mp4">Cheer</button>
|
||||
<button class="menu-item" data-video="视频资源/生成跳舞视频.mp4">Dance</button>
|
||||
</div>
|
||||
|
||||
<!-- 底部麦克风和链接 -->
|
||||
<footer class="bottom-bar">
|
||||
<button class="mic-button" id="mic-button" aria-label="Start Listening">
|
||||
|
||||
@@ -15,6 +15,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
let video2 = document.getElementById('video2');
|
||||
const micButton = document.getElementById('mic-button');
|
||||
const favorabilityBar = document.getElementById('favorability-bar');
|
||||
const floatingButton = document.getElementById('floating-button');
|
||||
const menuContainer = document.getElementById('menu-container');
|
||||
const menuItems = document.querySelectorAll('.menu-item');
|
||||
|
||||
let activeVideo = video1;
|
||||
let inactiveVideo = video2;
|
||||
@@ -134,6 +137,51 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
});
|
||||
|
||||
|
||||
// --- 悬浮按钮交互 ---
|
||||
floatingButton.addEventListener('click', (event) => {
|
||||
event.stopPropagation(); // 防止事件冒泡到 document
|
||||
menuContainer.classList.toggle('hidden');
|
||||
});
|
||||
|
||||
menuItems.forEach(item => {
|
||||
item.addEventListener('click', function() {
|
||||
const videoSrc = this.getAttribute('data-video');
|
||||
playSpecificVideo(videoSrc);
|
||||
menuContainer.classList.add('hidden');
|
||||
});
|
||||
});
|
||||
|
||||
// 点击菜单外部区域关闭菜单
|
||||
document.addEventListener('click', () => {
|
||||
if (!menuContainer.classList.contains('hidden')) {
|
||||
menuContainer.classList.add('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
// 阻止菜单自身的点击事件冒泡
|
||||
menuContainer.addEventListener('click', (event) => {
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
|
||||
function playSpecificVideo(videoSrc) {
|
||||
const currentVideoSrc = activeVideo.querySelector('source').getAttribute('src');
|
||||
if (videoSrc === currentVideoSrc) return;
|
||||
|
||||
inactiveVideo.querySelector('source').setAttribute('src', videoSrc);
|
||||
inactiveVideo.load();
|
||||
|
||||
inactiveVideo.addEventListener('canplaythrough', function onCanPlayThrough() {
|
||||
inactiveVideo.removeEventListener('canplaythrough', onCanPlayThrough);
|
||||
activeVideo.pause(); // 暂停当前视频,防止其 'ended' 事件触发切换
|
||||
inactiveVideo.play().catch(error => console.error("Video play failed:", error));
|
||||
activeVideo.classList.remove('active');
|
||||
inactiveVideo.classList.add('active');
|
||||
[activeVideo, inactiveVideo] = [inactiveVideo, activeVideo];
|
||||
activeVideo.addEventListener('ended', switchVideo, { once: true });
|
||||
}, { once: true });
|
||||
}
|
||||
|
||||
// --- 情感分析与反应 ---
|
||||
const positiveWords = ['开心', '高兴', '喜欢', '太棒了', '你好', '漂亮'];
|
||||
const negativeWords = ['难过', '生气', '讨厌', '伤心'];
|
||||
@@ -179,6 +227,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
inactiveVideo.addEventListener('canplaythrough', function onCanPlayThrough() {
|
||||
inactiveVideo.removeEventListener('canplaythrough', onCanPlayThrough);
|
||||
activeVideo.pause(); // 暂停当前视频,防止其 'ended' 事件触发切换
|
||||
inactiveVideo.play().catch(error => console.error("Video play failed:", error));
|
||||
activeVideo.classList.remove('active');
|
||||
inactiveVideo.classList.add('active');
|
||||
|
||||
@@ -152,6 +152,78 @@ html, body {
|
||||
text-shadow: 1px 1px 2px rgba(0,0,0,0.7);
|
||||
}
|
||||
|
||||
/* --- 悬浮按钮和菜单 --- */
|
||||
#floating-button {
|
||||
position: fixed;
|
||||
bottom: 120px; /* 调整位置,使其在麦克风按钮上方 */
|
||||
right: 30px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
#floating-button:hover {
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
#floating-button i {
|
||||
font-size: 24px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#menu-container {
|
||||
position: fixed;
|
||||
bottom: 200px; /* 调整位置,使其在悬浮按钮上方 */
|
||||
right: 30px;
|
||||
width: 150px;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||||
z-index: 9;
|
||||
transition: opacity 0.3s ease, transform 0.3s ease;
|
||||
transform-origin: bottom right;
|
||||
}
|
||||
|
||||
#menu-container.hidden {
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
background: none;
|
||||
border: none;
|
||||
color: white;
|
||||
font-size: 1rem;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.menu-item:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
|
||||
/* --- 底部内容 --- */
|
||||
.bottom-bar {
|
||||
width: 100%;
|
||||
|
||||
Reference in New Issue
Block a user