You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
324 lines
9.6 KiB
324 lines
9.6 KiB
/**
|
|
* 视频横幅功能脚本
|
|
* 处理视频播放、视频背景和GSAP动画
|
|
*/
|
|
|
|
// 全局变量
|
|
let videoBannerInitialized = false;
|
|
|
|
// 视频模态框功能
|
|
function openVideoModal(element) {
|
|
const container = element.closest('.video-banner-container');
|
|
if (!container) return;
|
|
|
|
const videoUrl = container.getAttribute('data-video-url');
|
|
const videoTitle = container.getAttribute('data-video-title') || '视频播放';
|
|
|
|
if (!videoUrl) return;
|
|
|
|
const modal = document.getElementById('video-modal');
|
|
const modalVideo = document.getElementById('modal-video');
|
|
const modalTitle = document.getElementById('video-modal-title');
|
|
|
|
if (modal && modalVideo && modalTitle) {
|
|
modalTitle.textContent = videoTitle;
|
|
modalVideo.src = videoUrl;
|
|
modal.style.display = 'block';
|
|
|
|
// 添加动画效果
|
|
if (typeof gsap !== 'undefined') {
|
|
gsap.fromTo(modal.querySelector('.video-modal-content'),
|
|
{ scale: 0.8, opacity: 0 },
|
|
{ scale: 1, opacity: 1, duration: 0.3, ease: "back.out(1.7)" }
|
|
);
|
|
}
|
|
|
|
// 阻止背景滚动
|
|
document.body.style.overflow = 'hidden';
|
|
}
|
|
}
|
|
|
|
function closeVideoModal() {
|
|
const modal = document.getElementById('video-modal');
|
|
const modalVideo = document.getElementById('modal-video');
|
|
|
|
if (modal && modalVideo) {
|
|
// 添加关闭动画
|
|
if (typeof gsap !== 'undefined') {
|
|
gsap.to(modal.querySelector('.video-modal-content'), {
|
|
scale: 0.8,
|
|
opacity: 0,
|
|
duration: 0.2,
|
|
ease: "power2.in",
|
|
onComplete: () => {
|
|
modal.style.display = 'none';
|
|
modalVideo.src = '';
|
|
document.body.style.overflow = '';
|
|
}
|
|
});
|
|
} else {
|
|
modal.style.display = 'none';
|
|
modalVideo.src = '';
|
|
document.body.style.overflow = '';
|
|
}
|
|
}
|
|
}
|
|
|
|
// 视频背景管理
|
|
class VideoBannerManager {
|
|
constructor() {
|
|
this.containers = [];
|
|
this.init();
|
|
}
|
|
|
|
init() {
|
|
this.findContainers();
|
|
this.setupEventListeners();
|
|
this.initializeVideos();
|
|
this.setupAnimations();
|
|
}
|
|
|
|
findContainers() {
|
|
this.containers = Array.from(document.querySelectorAll('.video-banner-container'));
|
|
}
|
|
|
|
setupEventListeners() {
|
|
// 窗口调整大小时重新初始化
|
|
window.addEventListener('resize', this.debounce(() => {
|
|
this.handleResize();
|
|
}, 250));
|
|
|
|
// 模态框点击外部关闭
|
|
const modal = document.getElementById('video-modal');
|
|
if (modal) {
|
|
modal.addEventListener('click', (e) => {
|
|
if (e.target === modal) {
|
|
closeVideoModal();
|
|
}
|
|
});
|
|
}
|
|
|
|
// ESC键关闭模态框
|
|
document.addEventListener('keydown', (e) => {
|
|
if (e.key === 'Escape') {
|
|
closeVideoModal();
|
|
}
|
|
});
|
|
}
|
|
|
|
initializeVideos() {
|
|
this.containers.forEach(container => {
|
|
const video = container.querySelector('.video-background');
|
|
if (video) {
|
|
this.setupVideo(video, container);
|
|
}
|
|
});
|
|
}
|
|
|
|
setupVideo(video, container) {
|
|
// 设置视频属性
|
|
video.muted = true;
|
|
video.loop = true;
|
|
video.playsInline = true;
|
|
video.autoplay = true;
|
|
|
|
// 监听视频事件
|
|
video.addEventListener('loadeddata', () => {
|
|
this.onVideoLoaded(video, container);
|
|
});
|
|
|
|
video.addEventListener('canplay', () => {
|
|
this.playVideo(video);
|
|
});
|
|
|
|
video.addEventListener('error', (e) => {
|
|
console.error('视频加载失败:', e);
|
|
this.handleVideoError(video, container);
|
|
});
|
|
|
|
// 尝试播放视频
|
|
this.playVideo(video);
|
|
}
|
|
|
|
onVideoLoaded(video, container) {
|
|
// 视频加载完成后的处理
|
|
video.style.opacity = '1';
|
|
|
|
// 添加淡入动画
|
|
if (typeof gsap !== 'undefined') {
|
|
gsap.fromTo(video,
|
|
{ opacity: 0 },
|
|
{ opacity: 1, duration: 1, ease: "power2.out" }
|
|
);
|
|
}
|
|
}
|
|
|
|
playVideo(video) {
|
|
const playPromise = video.play();
|
|
|
|
if (playPromise !== undefined) {
|
|
playPromise.then(() => {
|
|
// 自动播放成功
|
|
|
|
}).catch(error => {
|
|
// 自动播放失败,通常是由于浏览器政策
|
|
|
|
this.handleAutoplayFailure(video);
|
|
});
|
|
}
|
|
}
|
|
|
|
handleAutoplayFailure(video) {
|
|
// 创建播放按钮
|
|
const container = video.closest('.video-banner-container');
|
|
if (container && !container.querySelector('.video-play-trigger')) {
|
|
const playButton = document.createElement('div');
|
|
playButton.className = 'video-play-trigger';
|
|
playButton.innerHTML = `
|
|
<div class="play-icon-overlay">
|
|
<svg width="80" height="80" viewBox="0 0 80 80" fill="none">
|
|
<circle cx="40" cy="40" r="40" fill="rgba(255,255,255,0.9)"/>
|
|
<polygon points="32,25 32,55 55,40" fill="#333"/>
|
|
</svg>
|
|
</div>
|
|
`;
|
|
|
|
playButton.addEventListener('click', () => {
|
|
video.play();
|
|
playButton.remove();
|
|
});
|
|
|
|
container.appendChild(playButton);
|
|
}
|
|
}
|
|
|
|
handleVideoError(video, container) {
|
|
// 视频加载错误处理
|
|
const errorDiv = document.createElement('div');
|
|
errorDiv.className = 'video-error-message';
|
|
errorDiv.textContent = '视频加载失败';
|
|
container.appendChild(errorDiv);
|
|
}
|
|
|
|
handleResize() {
|
|
// 处理窗口大小变化
|
|
this.containers.forEach(container => {
|
|
const video = container.querySelector('.video-background');
|
|
if (video) {
|
|
this.adjustVideoSize(video, container);
|
|
}
|
|
});
|
|
}
|
|
|
|
adjustVideoSize(video, container) {
|
|
// 调整视频尺寸以适应容器
|
|
const containerRect = container.getBoundingClientRect();
|
|
const videoRect = video.getBoundingClientRect();
|
|
|
|
const containerRatio = containerRect.width / containerRect.height;
|
|
const videoRatio = video.videoWidth / video.videoHeight;
|
|
|
|
if (containerRatio > videoRatio) {
|
|
video.style.width = '100%';
|
|
video.style.height = 'auto';
|
|
} else {
|
|
video.style.width = 'auto';
|
|
video.style.height = '100%';
|
|
}
|
|
}
|
|
|
|
setupAnimations() {
|
|
if (typeof gsap === 'undefined') return;
|
|
|
|
// 等待GSAP兼容性就绪
|
|
if (!document.body.classList.contains('gsap-ready')) {
|
|
document.addEventListener('gsapCompatibilityReady', () => {
|
|
this.setupAnimations();
|
|
});
|
|
return;
|
|
}
|
|
|
|
this.containers.forEach(container => {
|
|
this.animateContainer(container);
|
|
});
|
|
}
|
|
|
|
animateContainer(container) {
|
|
const content = container.querySelector('.video-banner-content');
|
|
const title = container.querySelector('.video-banner-title');
|
|
const subtitle = container.querySelector('.video-banner-subtitle');
|
|
const description = container.querySelector('.video-banner-description');
|
|
const playButton = container.querySelector('.video-banner-play-button');
|
|
|
|
// 创建时间线动画
|
|
const tl = gsap.timeline({ delay: 0.5 });
|
|
|
|
if (subtitle) {
|
|
tl.fromTo(subtitle,
|
|
{ y: 30, opacity: 0 },
|
|
{ y: 0, opacity: 1, duration: 0.8, ease: "power2.out" }
|
|
);
|
|
}
|
|
|
|
if (title) {
|
|
tl.fromTo(title,
|
|
{ y: 50, opacity: 0 },
|
|
{ y: 0, opacity: 1, duration: 1, ease: "power2.out" },
|
|
"-=0.6"
|
|
);
|
|
}
|
|
|
|
if (description) {
|
|
tl.fromTo(description,
|
|
{ y: 30, opacity: 0 },
|
|
{ y: 0, opacity: 1, duration: 0.8, ease: "power2.out" },
|
|
"-=0.4"
|
|
);
|
|
}
|
|
|
|
if (playButton) {
|
|
tl.fromTo(playButton,
|
|
{ scale: 0, opacity: 0 },
|
|
{ scale: 1, opacity: 1, duration: 0.6, ease: "back.out(1.7)" },
|
|
"-=0.2"
|
|
);
|
|
}
|
|
}
|
|
|
|
// 工具函数:防抖
|
|
debounce(func, wait) {
|
|
let timeout;
|
|
return function executedFunction(...args) {
|
|
const later = () => {
|
|
clearTimeout(timeout);
|
|
func(...args);
|
|
};
|
|
clearTimeout(timeout);
|
|
timeout = setTimeout(later, wait);
|
|
};
|
|
}
|
|
}
|
|
|
|
// 初始化
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
if (!videoBannerInitialized) {
|
|
new VideoBannerManager();
|
|
videoBannerInitialized = true;
|
|
}
|
|
});
|
|
|
|
// 如果页面已经加载完成
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
if (!videoBannerInitialized) {
|
|
new VideoBannerManager();
|
|
videoBannerInitialized = true;
|
|
}
|
|
});
|
|
} else {
|
|
if (!videoBannerInitialized) {
|
|
new VideoBannerManager();
|
|
videoBannerInitialized = true;
|
|
}
|
|
}
|