HTML视频播放器进度条无法正常更新问题求助
视频进度条不更新的问题排查与修复
问题原因
- CSS与JS逻辑不匹配:你通过
#progress-bar::before伪元素实现进度高亮效果,但JavaScript代码错误地修改了进度条容器(#progress-bar)的宽度,而非伪元素的宽度——容器本身应保持满宽,伪元素的宽度才是对应播放进度的部分。 - 未处理视频加载状态:视频未完全加载时
video.duration为NaN,直接计算百分比会导致进度条无响应。
修复方案
1. 调整CSS样式
在原CSS基础上,给进度条容器添加CSS变量控制伪元素宽度,确保伪元素定位正确:
#progress-bar { flex-grow: 1; height: 5px; margin: 0 10px; position: relative; cursor: pointer; background-color: #555; width: 100%; /* 定义CSS变量控制进度宽度 */ --progress-width: 0%; } #progress-bar::before { content: ""; position: absolute; height: 100%; width: var(--progress-width); background-color: #fff; left: 0; top: 0; }
2. 修改JavaScript关键函数
替换以下几个函数的逻辑,确保正确控制进度伪元素,并处理视频未加载的情况:
function updateProgressBar() { if (isNaN(video.duration)) return; // 视频未加载完成时跳过更新 const percent = (video.currentTime / video.duration) * 100; // 通过CSS变量更新伪元素宽度 progressBar.style.setProperty('--progress-width', percent + '%'); currentTimeDisplay.textContent = formatTime(video.currentTime); } function seek(e) { if (isNaN(video.duration)) return; // 视频未加载时不响应点击 const percent = e.offsetX / progressBar.clientWidth; video.currentTime = percent * video.duration; } function handleVideoEnd() { playPauseBtn.innerHTML = "►"; // 重置进度伪元素宽度 progressBar.style.setProperty('--progress-width', '0%'); currentTimeDisplay.textContent = "0:00"; }
完整修复后代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Video Player</title> <style> body { font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; text-align: center; background-color: #222; margin: 0; padding: 0; color: #fff; } #video-container { max-width: 800px; margin: 20px auto; position: relative; } video { width: 100%; display: block; } #custom-controls { position: absolute; bottom: 0; left: 0; width: 100%; background-color: rgba(0, 0, 0, 0.7); display: flex; justify-content: space-between; padding: 10px; opacity: 0; transition: opacity 0.5s; box-sizing: border-box; } #video-container:hover #custom-controls { opacity: 1; } button, input { background: none; border: none; cursor: pointer; color: white; font-size: 16px; margin: 0 5px; } input[type="range"] { width: 150px; } #progress-bar-container { flex-grow: 1; display: flex; align-items: center; } #progress-bar { flex-grow: 1; height: 5px; margin: 0 10px; position: relative; cursor: pointer; background-color: #555; width: 100%; --progress-width: 0%; } #progress-bar::before { content: ""; position: absolute; height: 100%; width: var(--progress-width); background-color: #fff; left: 0; top: 0; } </style> </head> <body> <div id="video-container"> <video id="myVideo"> <source src="1.mp4" type="video/mp4" /> Your browser does not support the video tag. </video> <div id="custom-controls"> <button id="playPauseBtn">►</button> <input type="range" id="volumeRange" min="0" max="1" step="0.1" value="1" /> <span id="playbackSpeed">Speed: 1x</span> <input type="range" id="speedRange" min="0.5" max="2" step="0.1" value="1" /> <button id="muteBtn">Mute 🔇</button> <div id="progress-bar-container"> <span id="current-time">0:00</span> <div id="progress-bar"></div> <span id="duration">0:00</span> </div> <button id="fullscreenBtn">Full</button> </div> </div> <script> const video = document.getElementById("myVideo"); const playPauseBtn = document.getElementById("playPauseBtn"); const volumeRange = document.getElementById("volumeRange"); const speedRange = document.getElementById("speedRange"); const playbackSpeedDisplay = document.getElementById("playbackSpeed"); const muteBtn = document.getElementById("muteBtn"); const progressBar = document.getElementById("progress-bar"); const currentTimeDisplay = document.getElementById("current-time"); const durationDisplay = document.getElementById("duration"); const fullscreenBtn = document.getElementById("fullscreenBtn"); playPauseBtn.addEventListener("click", togglePlayPause); volumeRange.addEventListener("input", setVolume); speedRange.addEventListener("input", setSpeed); muteBtn.addEventListener("click", toggleMute); progressBar.addEventListener("click", seek); fullscreenBtn.addEventListener("click", toggleFullscreen); video.addEventListener("timeupdate", updateProgressBar); video.addEventListener("durationchange", updateDuration); video.addEventListener("ended", handleVideoEnd); function togglePlayPause() { if (video.paused) { video.play(); playPauseBtn.innerHTML = "❚❚"; } else { video.pause(); playPauseBtn.innerHTML = "►"; } } function setVolume() { video.volume = volumeRange.value; if (video.volume === 0) { muteBtn.innerHTML = "Unmute 🔊"; } else { muteBtn.innerHTML = "Mute 🔇"; } } function setSpeed() { video.playbackRate = speedRange.value; playbackSpeedDisplay.textContent = `Speed: ${speedRange.value}x`; } function toggleMute() { video.muted = !video.muted; if (video.muted) { muteBtn.innerHTML = "Unmute 🔊"; } else { muteBtn.innerHTML = "Mute 🔇"; } } function toggleFullscreen() { if (video.requestFullscreen) { video.requestFullscreen(); } else if (video.mozRequestFullScreen) { video.mozRequestFullScreen(); } else if (video.webkitRequestFullscreen) { video.webkitRequestFullscreen(); } } function seek(e) { if (isNaN(video.duration)) return; const percent = e.offsetX / progressBar.clientWidth; video.currentTime = percent * video.duration; } function updateProgressBar() { if (isNaN(video.duration)) return; const percent = (video.currentTime / video.duration) * 100; progressBar.style.setProperty('--progress-width', percent + '%'); currentTimeDisplay.textContent = formatTime(video.currentTime); } function updateDuration() { durationDisplay.textContent = formatTime(video.duration); } function formatTime(time) { const minutes = Math.floor(time / 60); const seconds = Math.floor(time % 60); return `${minutes}:${seconds < 10 ? "0" : ""}${seconds}`; } function handleVideoEnd() { playPauseBtn.innerHTML = "►"; progressBar.style.setProperty('--progress-width', '0%'); currentTimeDisplay.textContent = "0:00"; } </script> </body> </html>
内容的提问来源于stack exchange,提问作者Poniukas Pegasiukas
相关产品推荐
相关产品推荐

