通过移除video的controls属性并用controlsList限制默认行为,包裹自定义容器,结合Video API实现播放控制、进度拖拽、静音等功能,并用CSS完全重写UI样式。

直接用 JavaScript 替换原生控件,隐藏默认 UI,再用 HTML+CSS 构建新控制器,并通过 Video API 控制播放状态和进度。
1. 隐藏原生控件并准备自定义容器
在 <video> 标签中去掉 controls 属性,用 controlsList="nodownload nofullscreen noremoteplayback" 进一步限制默认行为。包裹一个带自定义类的容器,方便定位和样式控制:
<div class="custom-video-player">
<video id="myVideo" controlsList="nodownload nofullscreen noremoteplayback">
<source src="video.mp4" type="video/mp4">
</video>
<div class="custom-controls">
<button class="play-btn">▶</button>
<input type="range" class="progress-bar" min="0" max="100" value="0">
<span class="time-current">00:00</span>/<span class="time-duration">00:00</span>
<button class="mute-btn">?</button>
</div>
</div>2. 绑定核心事件与基础控制逻辑
获取 video 元素和各控制器节点,监听关键事件(如 loadedmetadata、timeupdate、ended),并实现播放/暂停、音量、静音、进度拖拽等操作:
const video = document.getElementById('myVideo');
const playBtn = document.querySelector('.play-btn');
const progressBar = document.querySelector('.progress-bar');
const timeCurrent = document.querySelector('.time-current');
const timeDuration = document.querySelector('.time-duration');
const muteBtn = document.querySelector('.mute-btn');
<p>// 播放/暂停切换
playBtn.addEventListener('click', () => {
if (video.paused) {
video.play().catch(e => console.warn('Play failed:', e));
} else {
video.pause();
}
});</p><p>// 更新播放时间显示
video.addEventListener('timeupdate', () => {
const current = Math.floor(video.currentTime);
const duration = Math.floor(video.duration || 0);
timeCurrent.textContent = formatTime(current);
timeDuration.textContent = formatTime(duration);
progressBar.value = video.duration ? (video.currentTime / video.duration) * 100 : 0;
});</p><p>// 进度条拖动
progressBar.addEventListener('input', () => {
const newTime = (progressBar.value / 100) * video.duration;
video.currentTime = newTime;
});</p><p>// 静音切换
muteBtn.addEventListener('click', () => {
video.muted = !video.muted;
muteBtn.textContent = video.muted ? '?' : '?';
});</p>注意:需补充 formatTime(seconds) 辅助函数(如 Math.floor(s / 60) + ':' + (s % 60).toString().padStart(2, '0'))。
立即学习“Java免费学习笔记(深入)”;
3. 处理加载与交互细节
视频元数据加载完成前,时长可能为 NaN;用户拖拽时需防止未就绪就设置 currentTime;还要处理播放失败、网络中断等异常:
- 监听
loadedmetadata再初始化进度条最大值和总时长显示 - 拖拽
input事件触发时,先检查video.readyState >= 1再执行跳转 - 给
video.play()加.catch()避免自动播放被浏览器拦截时报错阻塞逻辑 - 可监听
waiting和canplay来显示加载状态(如旋转图标)
4. CSS 实现真正“完全自定义”外观
所有按钮、滑块、文字都可自由设计。关键是重置原生 <input type="range"> 样式(不同浏览器需分别处理):
.custom-controls {
display: flex;
align-items: center;
padding: 8px;
background: rgba(0,0,0,0.7);
border-radius: 4px;
}
.play-btn, .mute-btn {
background: none;
border: none;
color: white;
font-size: 18px;
cursor: pointer;
width: 36px;
height: 36px;
border-radius: 50%;
transition: background 0.2s;
}
.play-btn:hover { background: rgba(255,255,255,0.1); }
<p>.progress-bar {
-webkit-appearance: none;
height: 4px;
flex: 1;
margin: 0 12px;
background: #333;
border-radius: 2px;
}
.progress-bar::-webkit-slider-thumb {
-webkit-appearance: none;
width: 16px;
height: 16px;
border-radius: 50%;
background: #fff;
cursor: pointer;
}</p>其他样式(如全屏按钮、音量条、画中画开关)按需添加即可,结构与逻辑保持一致。



















