HTML5视频控制滑块max值偶现NaN问题排查与解决方法
视频进度滑动条实现及异常修复
功能需求
现有一个视频元素,下方配套滑动条,需要实现以下功能:
- 点击视频即可触发播放/暂停
- 视频播放时滑动条会同步跟随进度移动
- 手动拖动滑动条可调整视频的播放进度
问题描述
初始实现代码运行时,偶尔会出现滑动条max值为NaN的异常:本地打开index.html时滑动条max值始终正常,但部署到服务器后,该问题高频出现,无法正常获取视频时长设置滑动条参数。
问题根因
初始代码在document.onreadystatechange回调中读取视频时长,但是页面DOM加载完成不代表视频元数据(包含时长、分辨率等信息)加载完成,服务端部署时受网络延迟影响,元数据加载晚于DOM加载的概率更高,此时读取vid.duration就会得到NaN。
解决方案
修复思路如下:
- 为video标签添加
preload="metadata"属性,提示浏览器优先加载视频元数据 - 监听视频的
onloadedmetadata事件,待元数据加载完成后再设置滑动条的max值 - 初始隐藏滑动条,元数据加载完成后再显示,避免用户看到状态异常的滑动条
完整修复代码
JS代码
// 100.0 代表滑动条精度为百分之一秒 window.sliderResolution = 100.0 // 元数据加载完成后再设置滑动条最大值,避免出现NaN var vid = document.getElementById("vid") var slider = document.getElementById("myRange") vid.onloadedmetadata = function() { slider.min = 0 slider.value = 0 slider.max = vid.duration * window.sliderResolution console.log('slider min', slider.min) console.log('slider max', slider.max) // 元数据加载完成后显示滑动条 var slideParent = document.getElementById("slideparent") slideParent.style.visibility = "visible" }; document.onreadystatechange = function() { if (document.readyState == "complete") { console.log('Doc is ready') } } // 点击视频切换播放/暂停状态 var vid = document.getElementById("vid"); vid.addEventListener('click', (e) => { if (vid.paused) { vid.play() } else { vid.pause() } }); // 视频播放时同步更新滑动条位置 var vid = document.getElementById("vid"); var slider = document.getElementById("myRange"); vid.addEventListener("timeupdate", function(e) { t = this.currentTime slider.value = t * window.sliderResolution }); // 拖动滑动条调整视频播放进度 var vid = document.getElementById("vid"); var slider = document.getElementById("myRange"); slider.oninput = function() { vid.currentTime = slider.value / window.sliderResolution }
CSS代码
.slidecontainer { width: 100%; /* 外层容器宽度 */ margin-bottom: 20px; } /* 滑动条样式 */ .slider { -webkit-appearance: none; /* 覆盖默认CSS样式 */ appearance: none; width: 50%; height: 5px; background: #d3d3d3; /* 灰色背景 */ outline: none; /* 移除外描边 */ opacity: 0.7; /* 默认透明度,hover时有过渡效果 */ -webkit-transition: .2s; /* hover过渡动画0.2秒 */ transition: opacity .2s; } /* 鼠标悬停效果 */ .slider:hover { opacity: 1; /* 悬停时完全不透明 */ } /* 滑动条滑块样式(兼容Chrome、Opera、Safari、Edge) */ .slider::-webkit-slider-thumb { -webkit-appearance: none; /* 覆盖默认样式 */ appearance: none; width: 5px; height: 25px; background: #AA0000; cursor: pointer; /* 悬停时显示指针样式 */ } /* 滑动条滑块样式(兼容Firefox) */ .slider::-moz-range-thumb { width: 5px; height: 25px; background: #AA0000; cursor: pointer; }
HTML代码
<div style="width: 100%;"> <video id="vid" preload="metadata" style="width: 50%;"> <source id='mp4' src="http://media.w3.org/2010/05/sintel/trailer.mp4" type='video/mp4' /> <source id='webm' src="http://media.w3.org/2010/05/sintel/trailer.webm" type='video/webm' /> <source id='ogv' src="http://media.w3.org/2010/05/sintel/trailer.ogv" type='video/ogg' />Your browser does not support the vedio tag. </video> </div> <div class="slidecontainer" style="width: 100%; visibility: hidden;" id="slideparent"> <input type="range" min="1" max="100" value="50" class="slider" id="myRange"> </div>
内容的提问来源于stack exchange,提问作者Megidd
相关产品推荐
相关产品推荐

