自定义视频进度条更新跳变,如何实现平滑进度更新?
Hey there! I see the issue you're facing—your custom progress bar is updating in jumps instead of smoothly, even though the core functionality works. Let's break down why this happens and how to fix it.
Why the Jumps Happen
The timeupdate event doesn't fire continuously at a steady interval. Browsers typically trigger it every 250ms or so, but the timing can vary depending on video encoding, browser performance, and other factors. When you set the progress bar width directly from the timeupdate event, each jump in the reported currentTime translates directly to a jump in the bar's width—hence the choppy visual effect.
Solution 1: Quick Fix with CSS Transitions
The simplest way to add smoothness is to use CSS transitions to animate the width change. This lets the browser handle the smooth interpolation between each timeupdate value.
Modify your SASS code for the .timeElapsed class:
.timeElapsed { position: absolute; height: 100%; width: 0%; background: #000; transition: width 0.15s ease; /* Add this line */ }
- The
0.15svalue controls how fast the animation runs—adjust it to your preference (smaller = faster, larger = slower). easegives a natural acceleration/deceleration feel, but you can uselinearfor a constant speed if you prefer.
This requires almost no JS changes, and it'll immediately smooth out the jumps in your progress bar.
Solution 2: Precise Control with requestAnimationFrame
If you want more control over the smoothness (or if CSS transitions cause minor lag in some cases), use requestAnimationFrame to interpolate between the target progress values over time.
Here's the updated JS code:
var myVideo = document.querySelector('#myVideo'), timeElapsed = document.querySelector('.timeElapsed'), duration = 0, targetPercentage = 0, currentPercentage = 0; // Get video duration once it's loaded (avoids recalculating in timeupdate) myVideo.addEventListener('loadedmetadata', function() { duration = myVideo.duration; }); // Update the target percentage whenever timeupdate fires myVideo.addEventListener('timeupdate', function(){ if (!duration) return; // Skip if duration isn't loaded yet targetPercentage = (100 / duration) * myVideo.currentTime; }); // Smoothly interpolate progress using requestAnimationFrame function smoothProgressUpdate() { // Calculate the difference between target and current progress const progressDiff = targetPercentage - currentPercentage; // Move current progress toward the target (adjust 0.1 for smoothness) currentPercentage += progressDiff * 0.1; // Clamp values to 0-100% to avoid overshooting currentPercentage = Math.max(0, Math.min(100, currentPercentage)); timeElapsed.style.width = currentPercentage + '%'; // Keep the animation loop running requestAnimationFrame(smoothProgressUpdate); } // Start the smooth update loop requestAnimationFrame(smoothProgressUpdate);
- The
0.1multiplier controls how quickly the bar catches up to the target value. A higher number (like 0.3) will make it closer to instant updates, while a lower number (like 0.05) will make it slower and smoother. - We use
loadedmetadatato get the video duration once, instead of recalculating it everytimeupdate—this is more efficient.
Which Solution to Choose?
- Use the CSS transition method if you want a fast, low-effort fix that works for most cases.
- Use the
requestAnimationFramemethod if you need precise control over the animation speed or if you're building a more complex video player with additional custom animations.
Either approach will eliminate the jumpy progress bar you're seeing!
内容的提问来源于stack exchange,提问作者Mathieu Ferraris

