You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义JavaScript视频播放器进度条点击事件监听失效问题排查

自定义视频播放器进度条点击事件失效问题排查与解决

问题描述

我正在使用基础JavaScript开发一款自定义视频播放器,目前除进度条点击功能外,其余所有控件均正常工作:进度条可通过timeupdate事件正常更新播放进度。但尝试添加「用户点击进度条时,视频currentTime跳转到对应位置,同时进度条同步更新」的功能时,发现为进度条绑定的click事件监听(addEventListener)完全失效,scrub函数始终未被调用。

使用Bootstrap 4框架及基础CSS样式,相关代码如下:

HTML结构

<!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>
 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
 <link rel="stylesheet" href="videplayercss.css">
</head>
<body>
 <div class="videoplayer">
 <video src="yourvideo.mp4" autoplay class="videos">
 </video>
 </div>
 <div class="controlplayer">
 <div class="progress">
 <div class="progress-bar progress-bar-animated" role="progressbar" aria-valuenow="12" aria-valuemin="0" aria-valuemax="100" style="width: 25%; margin-bottom:5%;"></div>
 </div>
 <i class="fas fa-play"></i>
 <input type="range" min="0" max="1" value="1" step="0.01" id="volume">
 <input type="range" min="0.1" max="3" value="1" step="0.01" id="playbackspeed">
 <i class="fa fa-angle-double-left backward r">10s</i>
 <i class="fa fa-angle-double-right forward r">25s</i>
 </div>
 <script src="videoplayerjs.js"></script>
 <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
 <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
 <script src="https://kit.fontawesome.com/eb0a94b8cf.js" crossorigin="anonymous"></script>
</body>
</html>

CSS样式

body {
 background-color: blueviolet
}
.videos {
 width: 50%;
 margin-left:20%;
 margin-right: 20%;
 margin-top:10%;
}
.controlplayer {
 display:none;
 width: 50%;
 margin-left: 20%;
 margin-right: 20%;
 background-color: ;
}
#volume {
 width: 36%;
 position: relative;
 display: inline;
}
#playbackspeed {
 width:36%;
 position: relative;
 display: inline;
}
.r {
 background-color: Transparent;
 border: none;
 cursor:pointer;
 width: 9%;
 position: relative;
 display: inline;
}

JavaScript代码

let videoelement = document.querySelector('.videos')
let pausebutton = document.querySelector('.fas');
let skipbutton = document.querySelector('.forward');
let backbutton = document.querySelector('.backward');
let speed = document.querySelector('#playbackspeed');
let vol = document.querySelector('#volume');
let controls = document.querySelector('.controlplayer')
let progress = document.querySelector('.progress-bar')

vol.addEventListener('change', setvol)
vol.addEventListener('mousedown', setvol)
function setvol(e) {
 videoelement.volume = vol.value;
}

speed.addEventListener('change', rate)
speed.addEventListener('mousedown', rate)
function rate(e) {
 videoelement.playbackRate = speed.value;
}

pausebutton.addEventListener('click', playing)
videoelement.addEventListener('mouseenter', function () {
 controls.style.display = 'block';
})
videoelement.addEventListener('click', playing)
videoelement.addEventListener('play', updatebutton)
videoelement.addEventListener('pause', updatebutton)
videoelement.addEventListener('timeupdate', handleprogress)

function updatebutton() {
 if (videoelement.paused) {
 pausebutton.classList.remove('fa-pause')
 pausebutton.classList.add('fa-play')
 } else {
 pausebutton.classList.remove('fa-play')
 pausebutton.classList.add('fa-pause')
 }
}

function playing(e) {
 if (videoelement.paused) {
 videoelement.play();
 videoelement.controls = null;
 pausebutton.classList.remove('fa-play')
 pausebutton.classList.add('fa-pause')
 } else {
 videoelement.pause();
 pausebutton.classList.remove('fa-pause')
 pausebutton.classList.add('fa-play')
 }
}

skipbutton.addEventListener('click', function (e) {
 let t = videoelement.currentTime;
 if ((t + 25) < videoelement.duration)
 videoelement.currentTime = t + 25;
 else
 videoelement.currentTime = videoelement.duration;
})

backbutton.addEventListener('click', function (e) {
 let t = videoelement.currentTime;
 if ((t - 10) >= 0)
 videoelement.currentTime = t - 10;
 else
 videoelement.currentTime = 0;
})

function handleprogress() {
 let percent = (videoelement.currentTime / videoelement.duration) * 100;
 progress.style.width = `${percent}%`;
}

// 以下事件绑定完全失效,scrub函数未被调用
progress.addEventListener('click', scrub)
progress.addEventListener('mousemove', scrub)
function scrub(e) {
 console.log('sigjeg')
 // const scrubtime = (e.offsetX / progress.offsetWidth) * videoelement.duration;
 // videoelement.currentTime = scrubtime
}

问题原因分析

你遇到的核心问题是事件绑定的目标元素可点击范围太小,且父容器遮挡了点击区域:

  • Bootstrap的.progress是进度条的外层容器,而你把事件绑定在内部的.progress-bar上。当视频刚开始播放时,.progress-bar的宽度很小,用户点击进度条的大部分区域其实是点击在父容器.progress上,而不是.progress-bar,所以绑定的事件根本触发不了。
  • 你给.progress-bar设置了margin-bottom:5%,这让它和父容器之间出现空隙,进一步缩小了.progress-bar的可点击范围,加剧了问题。

不修改HTML结构的解决方案

我们只需要把事件监听转移到父容器.progress上,就能捕获到整个进度条区域的点击事件,同时调整scrub函数的计算逻辑即可:

修改后的JavaScript关键代码

// 替换原来的progress事件绑定,改为绑定到父容器.progress
const progressContainer = document.querySelector('.progress')
progressContainer.addEventListener('click', scrub)
// 优化:只有按住鼠标左键移动时才触发拖动
progressContainer.addEventListener('mousemove', function(e) {
  if(e.buttons === 1) {
    scrub(e)
  }
})

function scrub(e) {
  // 基于父容器的宽度计算跳转时间,而不是.progress-bar
  const scrubTime = (e.offsetX / progressContainer.offsetWidth) * videoelement.duration;
  // 确保时间在合法范围内
  videoelement.currentTime = Math.max(0, Math.min(scrubTime, videoelement.duration));
  // 手动触发进度更新,让进度条即时同步(可选,timeupdate会自动触发,但手动更流畅)
  handleprogress();
}

补充CSS优化

移除.progress-bar的margin-bottom,让进度条和父容器完全贴合,同时给父容器添加鼠标指针样式,提升用户体验:

.progress-bar {
  margin-bottom: 0; /* 移除原来的margin-bottom */
}

.progress {
  cursor: pointer; /* 提示用户进度条可点击 */
}

效果说明

修改后,点击进度条的任意位置都能触发跳转到对应播放进度,拖动鼠标时按住左键也能实时更新播放位置,完全符合需求,且不需要改动任何HTML结构。

内容的提问来源于stack exchange,提问作者Ankur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 04:17:41