视频观看至90%时‘Next video’按钮偶现不显示的修复方案
修复视频观看至90%时“Next video”按钮偶现不显示的问题
问题背景
我尝试使用JavaScript追踪视频的观看时长,需求是当用户观看视频至90%时显示“Next video”按钮,但该按钮有时正常显示,有时却不显示。以下是完整的HTML及JavaScript代码:
<head> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"> </head> <body> <div class="cursor-pointer pt-4 d-flex justify-content-center align-items-center flex-column"> <video class="w-50" poster="" id="plyr-video-player" playsinline controls> <source src="https://therapywebsite.s3.amazonaws.com/Binaural+Beats+Fast+5+min+meditation+Stress+Relief+%5Bxc3MacYfdbI%5D.mp4" type="video/mp4" /> </video> </div> <div class="pt-4 d-flex justify-content-center align-items-center flex-column"> <h5>Welcome to this session</h5> <button class=" d-none w-25 btn btn-primary me-3" id="next-video-btn">Next video</button> </div> <script> document.addEventListener("DOMContentLoaded", (event) => { const video = document.getElementById("plyr-video-player"); const nextVideoBtn = document.getElementById("next-video-btn"); const videoId = 1; const postInterval = 10; let playedCount = 0; let lastPlayedTime = 0; let totalWatchedTime = 0; let actualWatchedTime = 0; let isTabActive = true; let skipDetected = false; let isVideoVisible = true; document.addEventListener("visibilitychange", () => { isTabActive = !document.hidden; }); const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { isVideoVisible = entry.isIntersecting; }); }, {threshold: 0.5}); observer.observe(video); video.addEventListener("loadedmetadata", () => { const videoDuration = Math.floor(video.duration); const playedCountThreshold = Math.floor(videoDuration * 0.9); if (videoDuration){ console.log("Metadata loaded") } else{ console.log("Metadata isn't loaded yet!!") } const showVideoBtn = () =>{ if (video.currentTime > playedCountThreshold) { if (nextVideoBtn.classList.contains("d-none")) { nextVideoBtn.classList.remove("d-none"); } } }; function autoPlay() { return video.play(); } autoPlay().catch(error => { console.error("Autoplay failed:", error); }); setTimeout(autoPlay, 1000) function trackVideo(eventType, currentTime){ currentTime = Math.floor(currentTime); if (isTabActive && isVideoVisible){ if (currentTime > playedCountThreshold && lastPlayedTime <= playedCountThreshold) { playedCount++; } if (eventType !== "play" || eventType === "timeupdate"){ const timeDiff = Math.max(0, currentTime - lastPlayedTime); actualWatchedTime += timeDiff; } else if (eventType === "seeked") { skipDetected = true; const skippedTime = Math.max(0, currentTime - lastPlayedTime); actualWatchedTime -= skippedTime; } totalWatchedTime = actualWatchedTime; fetch("/track_video/", { method: "POST", headers: { "Content-Type": "application/json", "X-CSRFToken": "{{ csrf_token }}" }, body: JSON.stringify({ video_id: videoId, played_count: playedCount, video_duration: videoDuration, last_played_time: lastPlayedTime, total_watched_time: totalWatchedTime, }) }); } lastPlayedTime = currentTime; } video.addEventListener("play", () => trackVideo('play', video.currentTime)); video.addEventListener("pause", () => trackVideo("pause", video.currentTime)); video.addEventListener('timeupdate', () => { if (video.currentTime - lastPlayedTime >= postInterval) { trackVideo('timeupdate', video.currentTime); } showVideoBtn(); }); video.addEventListener("seeked", () =>{ skipDetected = true; lastPlayedTime = Math.floor(video.currentTime) trackVideo("seeked", video.currentTime) }); }); nextVideoBtn.addEventListener("click", () => { window.location.href = "/next_video.html"; }); }); </script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script> </body>
修复方案
1. 补充showVideoBtn的触发场景
当前仅在timeupdate事件中调用showVideoBtn,但用户直接快进至90%后、暂停在90%后,timeupdate不会触发,导致按钮不显示。需要在pause、seeked、ended事件中也触发按钮检查:
// 修改pause事件监听 video.addEventListener("pause", () => { trackVideo("pause", video.currentTime); showVideoBtn(); // 新增 }); // 修改seeked事件监听 video.addEventListener("seeked", () =>{ skipDetected = true; lastPlayedTime = Math.floor(video.currentTime); trackVideo("seeked", video.currentTime); showVideoBtn(); // 新增 }); // 新增ended事件监听 video.addEventListener("ended", showVideoBtn);
2. 优化showVideoBtn的判断逻辑
- 增加视频时长有效性校验,避免元数据加载异常时的误判
- 将判断条件从
>改为>=,覆盖刚好到达90%时长的边界场景 - 直接移除
d-none类,无需提前判断,简化逻辑且更可靠:
const showVideoBtn = () =>{ if (!videoDuration) return; // 校验时长有效性 if (video.currentTime >= playedCountThreshold) { nextVideoBtn.classList.remove("d-none"); } };
3. 确保阈值的实时可用性
将playedCountThreshold的计算移到showVideoBtn内部,避免因loadedmetadata未触发导致变量未定义的问题:
const showVideoBtn = () =>{ if (!video.duration) return; const playedCountThreshold = Math.floor(video.duration * 0.9); if (video.currentTime >= playedCountThreshold) { nextVideoBtn.classList.remove("d-none"); } };
4. 增加页面可见性变化时的检查
当页面从不可见切换回可见时,检查当前播放进度是否已达阈值,避免用户切回页面时按钮未显示:
document.addEventListener("visibilitychange", () => { isTabActive = !document.hidden; if (isTabActive) { showVideoBtn(); // 新增 } });
内容的提问来源于stack exchange,提问作者tribhuwan
相关产品推荐
相关产品推荐

