最终效果:
1、demo结构
fontawesome字体下载:http://fontawesome.dashgame.com/
loading.gif:百度loading.gif选择一张下载
2、index.html
功能包括:播放/暂停,全屏,跳播
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>自定义视频播放器</title> <link rel="stylesheet" href="./css/font-awesome.min.css"> <link rel="stylesheet" href="./css/index.css"> </head> <body> <h3 class="player-title">视频播放器</h3> <div class="player-container"> <video src="./mp4/test.mp4"></video> <div class="controls-container"> <!-- 播放/暂停 --> <a href="javascript:;" class="switch fa fa-play"></a> <!-- 全屏 --> <a href="javascript:;" class="expand fa fa-expand"></a> <!-- 进度条 --> <div class="progress"><!-- 进度条底色 --> <div class="bar"></div><!-- 进度条最外层,用于事件控制 --> <div class="loaded"></div><!-- 已加载 --> <div class="current-progress"></div><!-- 已播放 --> </div> <!-- 当前播放时间, 视频总长 --> <div class="time"> <span class="current-time">00:00:00</span> <span class="total-time">00:00:00</span> </div> </div> </div> <script type="text/javascript"> // 播放器 const video = document.querySelector('video'); // "播放/暂停"切换按钮 const switchBtn = document.querySelector('.switch'); // 当前播放时间span const currentTimeSpan = document.querySelector('.current-time') // 视频总时长 const totalTimeSpan = document.querySelector('.total-time') // 当前播放进度条 const currentProgress = document.querySelector('.current-progress') // 获取进度条最外层,用于事件控制 const bar = document.querySelector('.bar'); // 实现"播放/暂停" switchBtn.onclick = function() { // 播放与暂停的切换 if (video.paused) { video.play(); } else { video.pause(); } // 播放与暂停图标的切换 this.classList.toggle('fa-pause'); this.classList.toggle('fa-play'); } // 实现"全屏" const playerContainer = document.querySelector('.player-container'); document.querySelector('.expand').onclick = function() { if(playerContainer.requestFullScreen){ playerContainer.requestFullScreen(); } else if(playerContainer.webkitRequestFullScreen){ playerContainer.webkitRequestFullScreen(); } else if(playerContainer.mozRequestFullScreen){ playerContainer.mozRequestFullScreen(); } else if(playerContainer.msRequestFullScreen){ playerContainer.msRequestFullScreen(); } } // 当视频文件可以播放时触发 // 当跳播时,修改了video.currentTime,也会触发该事件 video.oncanplay = function() { console.log('触发oncanplay事件, video.currentTime=', video.currentTime) if (video.currentTime === 0) { setTimeout(function() { console.log('视频缓存完成,可以播放了。。。') // 显示视频第一帧画面 video.style.display = 'block' // 获取当前视频文件总时长 const totalTime = video.duration; console.log(`当前视频文件总时长: ${totalTime}秒`); // 单位为秒, 292.975736 // 页面显示视频总时长 totalTimeSpan.innerHTML = getTime(totalTime); }, 2000) } } // 当视频播放的时候会触发ontimeupdate事件,进度条同步,当前时间同步 // 当跳播时,修改了video.currentTime,也会触发该事件 video.ontimeupdate = function() { console.log('触发ontimeupdate事件。。。') // 获取当前时间 const currentTime = video.currentTime; // 计算出视频的总时长 const totalTime = video.duration; // 显示当前播放时间 currentTimeSpan.innerHTML = getTime(currentTime); //进度条同步: 当前时间/总时间 const value = currentTime / totalTime; currentProgress.style.width = value * 100 + "%"; //当播放完毕之后,播放暂停按钮要转换成暂停按钮 if (currentTime === totalTime) { switchBtn.classList.remove('fa-pause'); switchBtn.classList.add('fa-pause'); } } // 实现视频跳播 bar.onclick = function(e) { // 获取鼠标点击位置相对bar最左侧的距离 const offset = getOffsetX(e); // 获取bar的宽度 const barWidth = this.style.width || this.clientWidth || this.offsetWidth || this.scrollWidth; console.log(`offset=${offset}, barWidth=${barWidth}`) const percent = offset / barWidth; const currentTime = percent * video.duration; video.currentTime = currentTime; } function getTime(time) { //转换时长 let h = Math.floor(time / 3600); let m = Math.floor(time % 3600 / 60); let s = Math.floor(time % 60); //转换格式 h = h > 10 ? h : "0" + h; m = m > 10 ? m : "0" + m; s = s > 10 ? s : "0" + s; return h + ":" + m + ":" + s; } // 火狐浏览器不支持e.offsetX,解决方法 function getOffsetX(e){ var e = e || window.event; var srcObj = e.target || e.srcElement; if (e.offsetX) { return e.offsetX; } else { var rect = srcObj.getBoundingClientRect(); var clientx = e.clientX; return clientx - rect.left; } } </script> </body> </html>
3、index.css
body { padding: 0; margin: 0; font-family: 'microsofy yahei'; background-color: #F7F7F7; } a { text-decoration: none; } .player-title { width: 100%; margin: 0 auto; line-height: 100px; font-size: 40px; text-align: center; } .player-container { width: 720px; height: 360px; margin: 0 auto; background: url('../images/loading.gif') center no-repeat; background-size: cover; position: relative; } video { height: 100%; margin: 0 auto; display: none; } /* ================ 播放器控制面板样式 start ================ */ .controls-container { width: 720px; height: 40px; position: absolute; left: 0px; bottom: -40px; background-color: #000; } /* 播放/暂停 */ .controls-container .switch { width: 20px; height: 20px; display: block; font-size: 20px; color: #fff; position: absolute; left: 10px; top: 10px; } /* 全屏 */ .controls-container .expand { width: 20px; height: 20px; display: block; font-size: 20px; color: #fff; position: absolute; right: 10px; top: 10px; } /* 进度条 */ .controls-container .progress { width: 430px; height: 10px; position: absolute; left: 40px; bottom: 15px; background-color: #555; } .controls-container .progress .bar { /* 100%;*/ width: 430px; height: 100%; border-radius: 3px; cursor: pointer; position: absolute; left: 0; top: 0; opacity: 0; z-index: 999; } .controls-container .progress .loaded { width: 60%; /* 视频缓存的进度, 后期可动态变化 */ height: 100%; background-color: #999; border-radius: 3px; position: absolute; left: 0; top: 0; z-index: 2; } .controls-container .progress .current-progress { width: 0%; /* 初始播放进度为0 */ height: 100%; background-color: #fff; border-radius: 3px; position: absolute; left: 0; top: 0; z-index: 3; } .controls-container .time { height: 20px; position: absolute; left: 490px; top: 10px; color: #fff; font-size: 14px; } /* ================ 播放器控制面板样式 end ================ */
4、测试
1)打开index.html页面,视频加载完成打印"视频缓存完成,可以播放了。。。";
2)点击进度条某个位置,首先触发了bar.onclick事件,计算并更新video.currentTime;然后触发了ontimeupdate事件和oncanplay事件。
3)点击播放按钮;
4)播放完毕后,发现一个小bug
解决:
删除代码:
//当播放完毕之后,播放暂停按钮要转换成暂停按钮 // if (currentTime === totalTime) { // switchBtn.classList.remove('fa-pause'); // switchBtn.classList.add('fa-pause'); // }
添加代码:
// 视频播放完毕,重置播放状态为初始状态 video.onended = function() { video.currentTime = 0; switchBtn.classList.remove('fa-pause'); switchBtn.classList.add('fa-pause'); }
---