修复视频播放器时间轴预览问题:移动端适配故障求助
移动端视频播放器时间轴预览功能修复方案
问题背景
我使用HTML/JS/CSS开发了一款视频播放器并部署至正式服务器,该播放器在PC端高分辨率环境下运行正常,但在移动端存在适配问题,例如手指触摸时间轴时预览功能失效。
现有时间轴JS代码
// Timeline timelineContainer.addEventListener("mousemove", handleTimeLineUpdate) timelineContainer.addEventListener("mousedown", toggleScrubbing); document.addEventListener("mouseup", e => { if(isScrubbing) toggleScrubbing(e) }) document.addEventListener("mousemove", e => { if(isScrubbing) handleTimeLineUpdate(e) }) let isScrubbing = false; let wasPaused; function toggleScrubbing(e){ const rect = timelineContainer.getBoundingClientRect(); const percent = Math.min(Math.max(0, e.x - rect.x), rect.width)/rect.width; isScrubbing = (e.buttons & 1) === 1; videoContainer.classList.toggle("scrubbing", isScrubbing) if(isScrubbing){ wasPaused = video.paused; video.pause(); } else { video.currentTime = percent * video.duration; if(!wasPaused) video.play(); } handleTimeLineUpdate(e); } function handleTimeLineUpdate(e){ const rect = timelineContainer.getBoundingClientRect(); // e.x = position mous, rect.x = position timeline const percent = Math.min(Math.max(0, e.x - rect.x), rect.width)/rect.width; // /10 protože mám po 10 vterinach const previewImgNumber = Math.max(1, Math.floor((percent*video.duration)/10)); const previewImgSrc = `video/preview${previewImgNumber}.jpg`; // Uložení cesty k obrazku previewImg.src = previewImgSrc; timelineContainer.style.setProperty("--preview-position",percent); if(isScrubbing) { e.preventDefault(); thumbnailImg.src = previewImgSrc; timelineContainer.style.setProperty("--progress-position", percent); } }
移动端问题示意图

修复建议
问题核心是现有代码仅适配PC端鼠标事件,未处理移动端触摸事件,以下是具体修复步骤:
1. 添加触摸事件监听
在现有鼠标事件监听基础上,补充移动端触摸事件监听:
// 补充触摸事件监听 timelineContainer.addEventListener("touchstart", toggleScrubbing); timelineContainer.addEventListener("touchmove", handleTimeLineUpdate); document.addEventListener("touchend", e => { if(isScrubbing) toggleScrubbing(e); }); document.addEventListener("touchmove", e => { if(isScrubbing) handleTimeLineUpdate(e); });
2. 统一事件坐标获取逻辑
鼠标事件用e.x,但触摸事件坐标需从e.touches[0]中获取,封装通用函数兼容两种事件:
// 新增通用函数:获取事件的X坐标 function getEventX(e) { // 优先取触摸事件坐标,兼容鼠标事件 return e.touches?.[0]?.clientX || e.x; }
然后在toggleScrubbing和handleTimeLineUpdate中替换原e.x:
// 在toggleScrubbing中修改 const x = getEventX(e); const percent = Math.min(Math.max(0, x - rect.x), rect.width)/rect.width; // 在handleTimeLineUpdate中修改 const x = getEventX(e); const percent = Math.min(Math.max(0, x - rect.x), rect.width)/rect.width;
3. 调整触摸事件下的Scrubbing状态判断
触摸事件无e.buttons属性,需根据事件类型直接设置状态:
修改toggleScrubbing函数:
function toggleScrubbing(e){ const rect = timelineContainer.getBoundingClientRect(); const x = getEventX(e); const percent = Math.min(Math.max(0, x - rect.x), rect.width)/rect.width; // 根据事件类型设置scrubbing状态 if(e.type === "mousedown" || e.type === "touchstart"){ isScrubbing = true; } else if(e.type === "mouseup" || e.type === "touchend"){ isScrubbing = false; } else { // 兼容原有鼠标事件判断逻辑 isScrubbing = (e.buttons & 1) === 1; } videoContainer.classList.toggle("scrubbing", isScrubbing) if(isScrubbing){ wasPaused = video.paused; video.pause(); } else { video.currentTime = percent * video.duration; if(!wasPaused) video.play(); } handleTimeLineUpdate(e); }
4. 阻止触摸事件默认行为避免冲突
在触摸移动时阻止默认行为,防止页面滚动干扰时间轴操作:
if(isScrubbing) { e.preventDefault(); // 阻止触摸时的页面滚动 thumbnailImg.src = previewImgSrc; timelineContainer.style.setProperty("--progress-position", percent); }
5. 可选:优化移动端触摸目标大小
通过CSS调整时间轴触摸区域,符合移动端交互规范:
.timeline-container { min-height: 44px; /* 确保触摸目标足够大 */ }
内容的提问来源于stack exchange,提问作者user12580002
相关产品推荐
相关产品推荐

