翻转卡片悬停4秒自动播放预告片功能实现问题
解决方案
核心逻辑梳理
要实现通用的6张卡片悬停播放效果,关键要做到:每个卡片独立监听正面悬停事件、4秒延迟触发播放、播放时替换正面内容为适配尺寸的预告片、鼠标离开/播放结束自动恢复正面,同时避免与原有的点击翻转逻辑冲突。
具体代码实现
1. HTML结构(通用适配6张卡片)
每个卡片包含正面层、背面层,正面层预留预告片容器(默认隐藏):
<div class="movie-card"> <div class="card-inner"> <div class="card-front"> <!-- 正面海报 --> <img src="movie-poster-1.jpg" alt="电影1海报" class="poster"> <!-- 预告片容器 --> <div class="trailer-container"> <video class="trailer-video" src="trailer-1.mp4" muted playsinline></video> </div> </div> <div class="card-back"> <!-- 背面简介内容 --> <h3>电影1</h3> <p>电影简介...</p> </div> </div> </div> <!-- 重复上述结构生成剩下5张卡片,仅替换海报、视频路径及简介内容 -->
2. CSS样式(保证尺寸匹配与布局)
确保预告片容器完全覆盖正面,视频适配卡片尺寸:
.movie-card { width: 300px; height: 450px; perspective: 1000px; position: relative; cursor: pointer; margin: 10px; } .card-inner { width: 100%; height: 100%; transition: transform 0.6s; transform-style: preserve-3d; } .card-front, .card-back { width: 100%; height: 100%; position: absolute; backface-visibility: hidden; } .card-back { transform: rotateY(180deg); background: #222; color: #fff; padding: 20px; display: flex; flex-direction: column; justify-content: center; } /* 预告片容器样式:覆盖整个正面 */ .trailer-container { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: #000; display: none; z-index: 1; } .trailer-video { width: 100%; height: 100%; object-fit: cover; /* 视频适配卡片尺寸,保持比例 */ } /* 点击翻转的触发类 */ .flipped .card-inner { transform: rotateY(180deg); }
3. JavaScript逻辑(通用处理所有卡片)
为每个卡片绑定独立的悬停、播放、恢复事件,避免全局变量冲突:
// 获取所有电影卡片 const movieCards = document.querySelectorAll('.movie-card'); // 遍历每个卡片,绑定事件 movieCards.forEach(card => { const cardFront = card.querySelector('.card-front'); const trailerContainer = card.querySelector('.trailer-container'); const trailerVideo = card.querySelector('.trailer-video'); let hoverTimer = null; // 鼠标进入正面:启动4秒延迟播放 cardFront.addEventListener('mouseenter', () => { // 如果当前卡片是翻转状态(显示背面),不处理 if (card.classList.contains('flipped')) return; // 清除之前的延迟(防止多次悬停叠加) if (hoverTimer) clearTimeout(hoverTimer); hoverTimer = setTimeout(() => { // 显示预告片并播放 trailerContainer.style.display = 'block'; trailerVideo.play().catch(err => console.error('预告片播放失败:', err)); // 播放时禁用点击翻转,避免误操作 card.style.pointerEvents = 'none'; }, 4000); }); // 鼠标离开:取消延迟、停止播放并恢复正面 card.addEventListener('mouseleave', () => { clearTimeout(hoverTimer); trailerContainer.style.display = 'none'; trailerVideo.pause(); trailerVideo.currentTime = 0; // 重置视频到开头 card.style.pointerEvents = 'auto'; // 恢复点击功能 }); // 预告片播放结束:自动恢复正面 trailerVideo.addEventListener('ended', () => { trailerContainer.style.display = 'none'; card.style.pointerEvents = 'auto'; }); // 保留原有的点击翻转逻辑(播放时不触发) card.addEventListener('click', () => { if (trailerContainer.style.display === 'block') return; card.classList.toggle('flipped'); }); });
关键修正点说明
- 通用适配:通过
querySelectorAll遍历所有卡片,每个卡片独立维护自己的延迟计时器,避免全局变量冲突。 - 悬停逻辑修正:直接监听卡片正面的
mouseenter事件,同时判断卡片是否处于翻转状态,避免背面显示时误触发预告片。 - 尺寸匹配:用CSS绝对定位让预告片容器完全覆盖正面,
object-fit: cover保证视频填充卡片且比例正常。 - 状态恢复:鼠标离开立即取消延迟、重置视频;播放结束自动隐藏预告片,恢复点击功能。
- 冲突避免:播放预告片时禁用卡片点击,防止误触发翻转;点击翻转时如果预告片正在播放,不执行操作。
内容的提问来源于stack exchange,提问作者user14178341
相关产品推荐
相关产品推荐

