feat(video): improve video playback with cross-fade transition
Implement smooth transition between videos using CSS opacity animation Add support for multiple video elements to enable seamless switching
This commit is contained in:
11
index.html
11
index.html
@@ -11,11 +11,16 @@
|
|||||||
<body>
|
<body>
|
||||||
|
|
||||||
<!-- 视频背景 -->
|
<!-- 视频背景 -->
|
||||||
<video autoplay muted id="bg-video">
|
<div class="video-container">
|
||||||
<!-- 初始可以留空,或放一个默认视频 -->
|
<video autoplay muted class="bg-video active" id="video1">
|
||||||
<source id="video-source" src="视频资源/3D 建模图片制作.mp4" type="video/mp4">
|
<source src="视频资源/3D 建模图片制作.mp4" type="video/mp4">
|
||||||
Your browser does not support the video tag.
|
Your browser does not support the video tag.
|
||||||
</video>
|
</video>
|
||||||
|
<video muted class="bg-video" id="video2">
|
||||||
|
<source src="" type="video/mp4">
|
||||||
|
Your browser does not support the video tag.
|
||||||
|
</video>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 内容层,覆盖在视频之上 -->
|
<!-- 内容层,覆盖在视频之上 -->
|
||||||
<div class="content-overlay">
|
<div class="content-overlay">
|
||||||
|
|||||||
55
script.js
55
script.js
@@ -1,11 +1,14 @@
|
|||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
|
||||||
// 获取需要的 DOM 元素
|
// 获取需要的 DOM 元素
|
||||||
const bgVideo = document.getElementById('bg-video');
|
let video1 = document.getElementById('video1');
|
||||||
const videoSource = document.getElementById('video-source');
|
let video2 = document.getElementById('video2');
|
||||||
const micButton = document.getElementById('mic-button');
|
const micButton = document.getElementById('mic-button');
|
||||||
const favorabilityBar = document.getElementById('favorability-bar');
|
const favorabilityBar = document.getElementById('favorability-bar');
|
||||||
|
|
||||||
|
let activeVideo = video1;
|
||||||
|
let inactiveVideo = video2;
|
||||||
|
|
||||||
// 视频列表
|
// 视频列表
|
||||||
const videoList = [
|
const videoList = [
|
||||||
'视频资源/3D 建模图片制作.mp4',
|
'视频资源/3D 建模图片制作.mp4',
|
||||||
@@ -13,25 +16,45 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
'视频资源/生成加油视频.mp4'
|
'视频资源/生成加油视频.mp4'
|
||||||
];
|
];
|
||||||
|
|
||||||
// --- 视频随机播放功能 ---
|
// --- 视频交叉淡入淡出播放功能 ---
|
||||||
bgVideo.addEventListener('ended', function() {
|
function switchVideo() {
|
||||||
// 获取当前播放的视频
|
// 1. 选择下一个视频
|
||||||
const currentVideo = videoSource.getAttribute('src');
|
const currentVideoSrc = activeVideo.querySelector('source').getAttribute('src');
|
||||||
|
let nextVideoSrc = currentVideoSrc;
|
||||||
// 过滤掉当前视频,从剩下的视频中随机选择一个
|
while (nextVideoSrc === currentVideoSrc) {
|
||||||
let nextVideo = currentVideo;
|
|
||||||
while (nextVideo === currentVideo) {
|
|
||||||
const randomIndex = Math.floor(Math.random() * videoList.length);
|
const randomIndex = Math.floor(Math.random() * videoList.length);
|
||||||
nextVideo = videoList[randomIndex];
|
nextVideoSrc = videoList[randomIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置新的视频源并播放
|
// 2. 设置不活动的 video 元素的 source
|
||||||
videoSource.setAttribute('src', nextVideo);
|
inactiveVideo.querySelector('source').setAttribute('src', nextVideoSrc);
|
||||||
bgVideo.load();
|
inactiveVideo.load();
|
||||||
bgVideo.play().catch(error => {
|
|
||||||
|
// 3. 当不活动的视频可以播放时,执行切换
|
||||||
|
inactiveVideo.addEventListener('canplaythrough', function onCanPlayThrough() {
|
||||||
|
// 确保事件只触发一次
|
||||||
|
inactiveVideo.removeEventListener('canplaythrough', onCanPlayThrough);
|
||||||
|
|
||||||
|
// 4. 播放新视频
|
||||||
|
inactiveVideo.play().catch(error => {
|
||||||
console.error("Video play failed:", error);
|
console.error("Video play failed:", error);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
// 5. 切换 active class 来触发 CSS 过渡
|
||||||
|
activeVideo.classList.remove('active');
|
||||||
|
inactiveVideo.classList.add('active');
|
||||||
|
|
||||||
|
// 6. 更新角色
|
||||||
|
[activeVideo, inactiveVideo] = [inactiveVideo, activeVideo];
|
||||||
|
|
||||||
|
// 为新的 activeVideo 绑定 ended 事件
|
||||||
|
activeVideo.addEventListener('ended', switchVideo, { once: true });
|
||||||
|
}, { once: true }); // 使用 { once: true } 确保事件只被处理一次
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始启动
|
||||||
|
activeVideo.addEventListener('ended', switchVideo, { once: true });
|
||||||
|
|
||||||
|
|
||||||
// --- 麦克风按钮交互和好感度条模拟 ---
|
// --- 麦克风按钮交互和好感度条模拟 ---
|
||||||
let isListening = false;
|
let isListening = false;
|
||||||
|
|||||||
22
style.css
22
style.css
@@ -13,15 +13,29 @@ html, body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* --- 视频背景 --- */
|
/* --- 视频背景 --- */
|
||||||
#bg-video {
|
.video-container {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
z-index: -1; /* 将视频置于最底层 */
|
z-index: -1;
|
||||||
object-fit: cover; /* 默认填满整个屏幕(裁剪),JS会切换它 */
|
background-color: #1a1a1a;
|
||||||
background-color: #1a1a1a; /* 视频加载前的背景色 */
|
}
|
||||||
|
|
||||||
|
.bg-video {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 1.5s ease-in-out; /* 交叉淡入淡出动画 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-video.active {
|
||||||
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- 内容覆盖层 --- */
|
/* --- 内容覆盖层 --- */
|
||||||
|
|||||||
Reference in New Issue
Block a user