您的当前位置:首页正文

web前端:自定义视频播放器,原生js实现窗口自适应,视频/音量进度条应用

2024-11-28 来源:个人技术集锦

1.less页面包装,引用混合

//导入播放器基础css
@import "reset.less";
//定义进度条混合
.progress-bar-position() {
    position: relative;
}

.progress-bar-line() {
    //定位:位置不变
    position: absolute;
    //进度条:height:3px BG:#737373
    width: 100%;
    height: 3px;
    //总高25,这里是3,剩余22
    margin-top: 11px;
    background: #737373;
}

.progress-bar-btn() {
    //定位:拖拽
    position: absolute;
    //w/h:w9*h7 BG:white border-radius+2px solid
    width: 15px;
    height: 12px;
    background: white;
    border-radius: 5px;
    //总高7,这里是3,剩余4
    margin-top: -5px;
    background: steelblue;
}

.progress-bar-current() {
    //实时进度条
    position: absolute;
    left: 0;
    top: 0;
    width: 0;
    background: skyblue;
    //高度和line相同
    margin-top: 11px;
    height: 3px;
}

* {
    margin: 0;
    padding: 0;
}

#wrap {
    //全屏效果
    height: 100%;
    //overflow: hidden;
    //overflow: auto;
    //滚动条,x轴有,y轴hidden
    overflow-x: auto;
    overflow-y: hidden;
    //  position: absolute;
    //  width: 800px;
    //  height: 800px;
    background: #383838;
    //  border: 1xp solid steelblue;
    //  border-radius: 8%;
    //  box-shadow: 2px 5px 5px #000000;
    //  top: 50%;
    //  left: 50%;
    //  transform: translate3d(-50%,-50%,0);
    text-align: center;
    //避免div之间存在缝隙空间padding
    font-size: 0;
    h1 {
        color: white;
        font-weight: bold;
        font: 20px "微软雅黑";
        margin: 2% auto;
    }
    #video-control {
        //行定位
        position: relative;
        height: 25px;
        background: #2A2A2A;
        //这里设置最小宽度,需要在wrap中放开overflow:auto,否则不生效
        min-width: 600px;
        /*1.视频开关
         * 按钮行row:w:55 h:25
         * 按钮:w:9 h:11
         */
        .video-btn {
            position: absolute;
            width: 55px;
            height: 25px;
            //background: skyblue;
            //修改默认的left top=auto
            left: 0;
            top: 0;
            //span居中
            text-align: center;
            //总高25,span=11,余14空间,上下各7
            margin-top: 7px;
            span {
                display: inline-block;
                width: 9px;
                height: 11px;
                background: url(../img/icon.png) no-repeat;
                &:nth-child(1) {
                    background-position: 0px -23px;
                    margin-right: 10px;
                    //如果具备active属性,则位置移动到stop后面
                    &.active{
                        background-position: 0px -11px;  
                    }
                }
                &:nth-child(2) {
                    background-position: 0px 0px;
                }
            }
        }
        /*2.视频进度条:宽度自适应
         * margin:55 230 
         * height:3px
         * BG:#737373
         */
        .video-progress {
            //相对定位(基于control,需要将min-width给video-control),根据line和btn
            //position: relative;
            //上右下左,宽度自适应,不需要定位
            margin: 0 230px 0 55px;
            height: 25px;
            font-size: 20px;
            .progress-bar-position();
            .progress-line {
                .progress-bar-line();
                .progress-btn {
                    .progress-bar-btn();
                }
            }
            .progress-current {
                .progress-bar-current();
            }
        }
        //3.视频尾部模块
        .video-other-operation {
            //定位,基于video-control
            position: absolute;
            width: 230px;
            height: 25px;
            //不写right,默认auto,下一行,需要指定0
            right: 0;
            bottom: 0;
            //高度统一
            &>div {
                height: 25px;
                float: left;
            }
            //视频时间
            .video-time {
                font: 14px "微软雅黑";
                color: skyblue;
                line-height: 25px;
                text-align: center;
                width: 120px;
                
            }
            .video-audio {
                width: 80px;
                div {
                    height: 25px;
                    float: left;
                }
                .audio-switch {
                    width: 20px;
                    text-align: center;
                    span {
                        display: inline-block;
                        width: 12px;
                        height: 12px;
                        margin: 7px auto;
                        background: url(../img/icon.png) no-repeat;
                        background-position: 0 -34px;
                        &.active{
                            background-position: 0 -46px;
                        }
                    }
                }
                .audio-volume {
                    width: 60px;
                    .progress-bar-position();
                    .volume-line {
                        .progress-bar-line();
                        .volume-btn {
                           .progress-bar-btn();
                        }
                    }
                    .volume-current {
                        .progress-bar-current();
                    }
                }
            }
            .video-full-screen {
                width: 30px;
                text-align: center;
                span {
                    display: inline-block;
                    width: 12px;
                    height: 12px;
                    margin: 7px auto;
                    background: url(../img/icon.png) no-repeat;
                    background-position: 0 -58px;
                    &.active{
                        background-position: 0 -70px;
                    }
                }
            }
        }
    }
}

2.css生成样式

html,
body {
  height: 100%;
  overflow: hidden;
}
/**
 * Eric Meyer's Reset CSS v2.0 (http://meyerweb.com/eric/tools/css/reset/)
 * http://cssreset.com
 */
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video,
input {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font-weight: normal;
  vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article,
aside,
details,
figcaption,
figure,
footer,
header,
menu,
nav,
section {
  display: block;
}
body {
  line-height: 1;
}
blockquote,
q {
  quotes: none;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
  content: none;
}
table {
  border-collapse: collapse;
  border-spacing: 0;
}
/* custom */
a {
  color: #7e8c8d;
  text-decoration: none;
  -webkit-backface-visibility: hidden;
}
li {
  list-style: none;
}
::-webkit-scrollbar {
  width: 5px;
  height: 5px;
}
::-webkit-scrollbar-track-piece {
  background-color: rgba(0, 0, 0, 0.2);
  -webkit-border-radius: 6px;
}
::-webkit-scrollbar-thumb:vertical {
  height: 5px;
  background-color: rgba(125, 125, 125, 0.7);
  -webkit-border-radius: 6px;
}
::-webkit-scrollbar-thumb:horizontal {
  width: 5px;
  background-color: rgba(125, 125, 125, 0.7);
  -webkit-border-radius: 6px;
}
html,
body {
  width: 100%;
}
body {
  -webkit-text-size-adjust: none;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
* {
  margin: 0;
  padding: 0;
}
#wrap {
  height: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  background: #383838;
  text-align: center;
  font-size: 0;
}
#wrap h1 {
  color: white;
  font-weight: bold;
  font: 20px "微软雅黑";
  margin: 2% auto;
}
#wrap #video-control {
  position: relative;
  height: 25px;
  background: #2A2A2A;
  min-width: 600px;
  /*1.视频开关
         * 按钮行row:w:55 h:25
         * 按钮:w:9 h:11
         */
  /*2.视频进度条:宽度自适应
         * margin:55 230 
         * height:3px
         * BG:#737373
         */
}
#wrap #video-control .video-btn {
  position: absolute;
  width: 55px;
  height: 25px;
  left: 0;
  top: 0;
  text-align: center;
  margin-top: 7px;
}
#wrap #video-control .video-btn span {
  display: inline-block;
  width: 9px;
  height: 11px;
  background: url(../img/icon.png) no-repeat;
}
#wrap #video-control .video-btn span:nth-child(1) {
  background-position: 0px -23px;
  margin-right: 10px;
}
#wrap #video-control .video-btn span:nth-child(1).active {
  background-position: 0px -11px;
}
#wrap #video-control .video-btn span:nth-child(2) {
  background-position: 0px 0px;
}
#wrap #video-control .video-progress {
  margin: 0 230px 0 55px;
  height: 25px;
  font-size: 20px;
  position: relative;
}
#wrap #video-control .video-progress .progress-line {
  position: absolute;
  width: 100%;
  height: 3px;
  margin-top: 11px;
  background: #737373;
}
#wrap #video-control .video-progress .progress-line .progress-btn {
  position: absolute;
  width: 15px;
  height: 12px;
  background: white;
  border-radius: 5px;
  margin-top: -5px;
  background: steelblue;
}
#wrap #video-control .video-progress .progress-current {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  background: skyblue;
  margin-top: 11px;
  height: 3px;
}
#wrap #video-control .video-other-operation {
  position: absolute;
  width: 230px;
  height: 25px;
  right: 0;
  bottom: 0;
}
#wrap #video-control .video-other-operation > div {
  height: 25px;
  float: left;
}
#wrap #video-control .video-other-operation .video-time {
  font: 14px "微软雅黑";
  color: skyblue;
  line-height: 25px;
  text-align: center;
  width: 120px;
}
#wrap #video-control .video-other-operation .video-audio {
  width: 80px;
}
#wrap #video-control .video-other-operation .video-audio div {
  height: 25px;
  float: left;
}
#wrap #video-control .video-other-operation .video-audio .audio-switch {
  width: 20px;
  text-align: center;
}
#wrap #video-control .video-other-operation .video-audio .audio-switch span {
  display: inline-block;
  width: 12px;
  height: 12px;
  margin: 7px auto;
  background: url(../img/icon.png) no-repeat;
  background-position: 0 -34px;
}
#wrap #video-control .video-other-operation .video-audio .audio-switch span.active {
  background-position: 0 -46px;
}
#wrap #video-control .video-other-operation .video-audio .audio-volume {
  width: 60px;
  position: relative;
}
#wrap #video-control .video-other-operation .video-audio .audio-volume .volume-line {
  position: absolute;
  width: 100%;
  height: 3px;
  margin-top: 11px;
  background: #737373;
}
#wrap #video-control .video-other-operation .video-audio .audio-volume .volume-line .volume-btn {
  position: absolute;
  width: 15px;
  height: 12px;
  background: white;
  border-radius: 5px;
  margin-top: -5px;
  background: steelblue;
}
#wrap #video-control .video-other-operation .video-audio .audio-volume .volume-current {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  background: skyblue;
  margin-top: 11px;
  height: 3px;
}
#wrap #video-control .video-other-operation .video-full-screen {
  width: 30px;
  text-align: center;
}
#wrap #video-control .video-other-operation .video-full-screen span {
  display: inline-block;
  width: 12px;
  height: 12px;
  margin: 7px auto;
  background: url(../img/icon.png) no-repeat;
  background-position: 0 -58px;
}
#wrap #video-control .video-other-operation .video-full-screen span.active {
  background-position: 0 -70px;
}

3.Reset.css引用样式

html,
body {
  height: 100%;
  overflow: hidden;
}
/**
 * Eric Meyer's Reset CSS v2.0 (http://meyerweb.com/eric/tools/css/reset/)
 * http://cssreset.com
 */
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video,
input {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font-weight: normal;
  vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article,
aside,
details,
figcaption,
figure,
footer,
header,
menu,
nav,
section {
  display: block;
}
body {
  line-height: 1;
}
blockquote,
q {
  quotes: none;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
  content: none;
}
table {
  border-collapse: collapse;
  border-spacing: 0;
}
/* custom */
a {
  color: #7e8c8d;
  text-decoration: none;
  -webkit-backface-visibility: hidden;
}
li {
  list-style: none;
}
::-webkit-scrollbar {
  width: 5px;
  height: 5px;
}
::-webkit-scrollbar-track-piece {
  background-color: rgba(0, 0, 0, 0.2);
  -webkit-border-radius: 6px;
}
::-webkit-scrollbar-thumb:vertical {
  height: 5px;
  background-color: rgba(125, 125, 125, 0.7);
  -webkit-border-radius: 6px;
}
::-webkit-scrollbar-thumb:horizontal {
  width: 5px;
  background-color: rgba(125, 125, 125, 0.7);
  -webkit-border-radius: 6px;
}
html,
body {
  width: 100%;
}
body {
  -webkit-text-size-adjust: none;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}

4.Video-btn-drag拖拽组件Js,函数自调用

/*
 * 拖拽组件,函数自调用
 * 传入参数window,wind=window
 */
(function(wind) {
	//1.为wind绑定对象属性${}
	wind.dragFunc = {};
	//2.callBack暴露拖拽,${}绑定属性dragger
	//js函数:形参列表可以和实参列表不一样
	wind.dragFunc.dragger = function(dragNode, callBack) {
		//1.dragNode初始化位置
		var initialPoint = {
			x: 0,
			y: 0
		};
		//1.鼠标(视口-包括浏览器窗口)初始化位置
		var mousePoint = {
			x: 0,
			y: 0
		};
		/*|--视口mousePoint-x(clientX)--|-------initialPoint鼠标落点-x(offsetLeft)------||*/
		/*|--视口mousePoint-x(clientX)--|-------initialPoint鼠标落点-x(offsetLeft)------|+|--movePoint鼠标移动店-x(clientX)-------|
		  鼠标移动点位置=initialPoint鼠标落点-x + movePoint鼠标移动店-x - mousePoint-x
		 * */
		//2.鼠标落下触发
		dragNode.onmousedown = function(e) {
			//兼容可简写:ev=ev || window.event;默认event带window.,如果ev存在 ||之后不执行 ,如果ev不存在 || 之后执行event
			e = e || event;

			//IE6-6兼容:全局捕获节点位置:setCapture
			if(dragNode.setCapture) {
				dragNode.setCapture();
			}

			//2.1鼠标落下获取:初始点位置
			initialPoint.x = dragNode.offsetLeft;
			initialPoint.y = dragNode.offsetTop;
			//鼠标落下获取:视口位置
			mousePoint.x = e.clientX;
			mousePoint.y = e.clientY;

			//2.3鼠标移动触发
			document.onmousemove = function(e) {
				e = e || event;
				var movePoint = {
					x: 0,
					y: 0
				};
				movePoint.x = e.clientX;
				movePoint.y = e.clientY;

				//这里开始移动,会偏移出x-offsetLeft
				//dragNode.style.left=initialPoint.x+(movePoint.x-mousePoint.x)+"px";

				var dragLeft = initialPoint.x + (movePoint.x - mousePoint.x);
				if(dragLeft < 0) {
					dragLeft = 0;
					//gragNode的width小于父级progress-line.width,需要减去offsetWidth,去掉多余部分
				} else if(dragLeft > dragNode.parentNode.clientWidth - dragNode.offsetWidth) {
					dragLeft = dragNode.parentNode.clientWidth - dragNode.offsetWidth
				}
				//开始移动
				dragNode.style.left = dragLeft + "px";
				/*进度条:progress-current跟踪
				 * 1.存在callBack对象
				 * 2.callback自定义属性有一个move
				 * 3.move的type=function函数,这里move函数在callBack对象中,调用时传入move函数
				 */
				if(callBack && callBack["move"] && typeof callBack["move"] === "function") {
					/*4.调用move函数(回调机制):obj['prop'](function);
					 * 调用js-->var obj={ 
					 * 	      prop:function(){
					 * 			} 
					 * 		}
					 */
					//第一种,在调用的js中获取dragNode的left
					//callBack["move"]();
					//第二种,call定义node
					callBack["move"].call(dragNode);
				}
			}

			document.onmouseup = function() {
				document.onmouseup = document.onmousemove = null;
				if(document.releaseCapture) {
					document.releaseCapture();
				}
			}

			return false;
		}
	}
})(window)

5.Video-player组件js

$(function() {
	var wrapNode = document.querySelector("#wrap");
	var videoNode = document.querySelector("#wrap > video");
	videoNode.poster = "./img/cubic-3D-camera-web全栈片头_Moment.jpg";
	var videoControlNode = document.querySelector("#wrap > #video-control");
	var videoProgressNode = document.querySelector("#wrap > #video-control > .video-progress");
	//视频进度拖拽btn
	var progressBtnNode = document.querySelector("#wrap > #video-control > .video-progress > .progress-line > .progress-btn");
	//视频进度条current
	var progressCurrentNode = document.querySelector("#wrap > #video-control > .video-progress > .progress-current");
	//进度条总长
	var progressLineNode = document.querySelector("#wrap > #video-control > .video-progress > .progress-line");

	//视频时间总长
	var videoDurationTimeNode = document.querySelector("#wrap > #video-control > .video-other-operation > .video-time > .duration-time");
	//视频当前时间
	var videoCurrentTimeNode = document.querySelector("#wrap > #video-control > .video-other-operation > .video-time > .current-time");
	//获取视频开关按钮
	var videoStartBtn = document.querySelector("#wrap > #video-control > .video-btn > .video-start");
	var videoStopBtn = document.querySelector("#wrap > #video-control > .video-btn > .video-stop");
	//获取音量开关
	var audioSwitchBtn = document.querySelector("#wrap > #video-control > .video-other-operation > .video-audio > .audio-switch");
	//音量按钮btn
	var volumnBtnNode = document.querySelector("#wrap > #video-control > .video-other-operation > .video-audio > .audio-volume > .volume-line > .volume-btn");
	//音量进度条current
	var volumnCurrentNode = document.querySelector("#wrap > #video-control > .video-other-operation > .video-audio > .audio-volume > .volume-current");
	//音量总长度
	var volumeLineNode = document.querySelector("#wrap > #video-control > .video-other-operation > .video-audio > .audio-volume > .volume-line");
	//音量开关
	var volumeSwitch = document.querySelector("#wrap > #video-control > .video-other-operation > .video-audio > .audio-switch >span");
	//同步音量控制
	var volumeSyncFlag = 0;

	//全屏按钮
	var fullScreenNode = document.querySelector("#wrap > #video-control > .video-other-operation > .video-full-screen");
	var fullScreen = document.querySelector("#wrap > #video-control > .video-other-operation > .video-full-screen > span");

	//1.设置视频宽高
	videoNode.width = 800;
	videoNode.height = document.documentElement.clientHeight - videoControlNode.offsetHeight;
	//videoNode.width=800;
	//2.每次用户视口调整,重新获取宽高,video-control<600的最小宽度,则不变
	window.onresize = function() {
		if(document.documentElement.clientWidth >= 600) {
			videoNode.width = document.documentElement.clientWidth;
			videoNode.height = document.documentElement.clientHeight - videoControlNode.offsetHeight;
		}
	}

	//3.视频进度条
	//callBack对象-->move属性-->存在func
	var callBack = {
		move: function() {
			console.log("progress-current开始移动=drag-->progressBtnNode.offsetLeft");
			//第一种,在这里调用progressCurrentNode的left,原生drag组件:callBack["move"]();
			//progressCurrentNode.style.width=progressBtnNode.offsetLeft+"px";
			//第二种,修改drag组件:callBack["move"].call(dragNode);
			progressCurrentNode.style.width = this.offsetLeft + "px";
			//1.获取拖动比率
			var dragRate = this.offsetLeft / (videoProgressNode.clientWidth - progressBtnNode.offsetWidth);
			//2.更新拖动视频时间
			videoNode.currentTime = videoNode.duration * dragRate;
		}
	}
	dragFunc.dragger(progressBtnNode, callBack);

	//5.视频开关按钮
	//定义暂停时间变量,避免进度条继续run
	var runTime = 0;
	videoPlay();

	function videoPlay() {

		//1.开始/暂停按钮
		videoStartBtn.onclick = function() {
			if(videoNode.paused) {
				//当前播放--》 播放时显示stop||点击暂停--》
				//兼容性高于:this.class.add 和 .remove
				addClass(this, "active");
				videoNode.play();
				//进度条run:
				runTime = setInterval(progressRun, 100);
			} else {
				removeClass(this, "active");
				videoNode.pause();
				//清理定时器时间戳
				clearInterval(runTime);
			}
		}
		//2. □ 恢复到初始化时间,并暂停
		videoStopBtn.onclick = function() {
			//这里要联动start按钮变化,不可以使用this
			removeClass(videoStartBtn, "active");
			videoNode.pause();
			clearInterval(runTime);
			//进度条返回原点
			progressBtnNode.style.left = progressCurrentNode.style.width = 0 + "px";
			//视频返回原点
			videoNode.currentTime = 0;
		}
		//3.拖拽<!--请求本地视频拖拽效果异常-->
		videoProgressNode.onclick = function(e) {
			e = e || event;
			addClass(videoStartBtn, "active");
			videoNode.play();
			runTime = setInterval(progressRun, 100);
			//跳到的位置:(持续时间*((视口距离-progressCurrent.offsetLeft)/(progress-line.clientWidth进度线总长 - progressBtnNode.offsetWidth按钮宽度)))
			console.log("拖拽到这里video-currentTime:", videoNode.currentTime);
			videoNode.currentTime = videoNode.duration * ((e.clientX - this.offsetLeft) / (videoProgressNode.clientWidth - progressBtnNode.offsetWidth));
			//更新时间
			videoCurrentTimeNode.innerHTML = timeFormat(videoNode.currentTime);
		}

		function progressRun() {
			//进度条宽度=按钮的left= 播放比例 (video.当前时间/video.持续时间)*(video-progress.clientWidth进度线总长 - progressBtnNode.offsetWidth按钮宽度)
			progressBtnNode.style.left = progressCurrentNode.style.width = (videoNode.currentTime / videoNode.duration) * (videoProgressNode.clientWidth - progressBtnNode.offsetWidth) + "px";
			//更新时间
			videoCurrentTimeNode.innerHTML = timeFormat(videoNode.currentTime);
		}

	}

	//6.视频时间:loadeddata	媒体的第一帧已经加载完毕。则进行时间获取
	videoNode.addEventListener("loadeddata", function() {
		//写入页面时,更新时间格式
		videoDurationTimeNode.innerHTML = timeFormat(videoNode.duration);
	})

	//7.音量控制
	volumnBtnNode.style.left = volumnCurrentNode.style.width = volumeLineNode.clientWidth - volumnBtnNode.offsetWidth + "px";
	audioSwitchBtn.onclick = function() {
		//静音时,显示不静音-->没有active
		if(videoNode.muted) {
			videoNode.muted = false;
			videoNode.volume = 1;
			removeClass(volumeSwitch, "active");
			//拖动后,进行比率运算
			volumeSyncFlag = volumeSyncFlag == 0 ? 1 : volumeSyncFlag;
			volumnBtnNode.style.left = volumnCurrentNode.style.width = (volumeLineNode.clientWidth - volumnBtnNode.offsetWidth) * volumeSyncFlag + "px";

		} else {
			videoNode.muted = true;
			videoNode.volume = 0;
			addClass(volumeSwitch, "active");
			volumnBtnNode.style.left = volumnCurrentNode.style.width = 0 + "px";
		}
	}
	//4.音量进度条
	var callBacks = {
		move: function() {
			volumnCurrentNode.style.width = this.offsetLeft + "px";
			//拖拽时控制音量比率(0-1)之间的比率
			var volumeRate = this.offsetLeft / (volumeLineNode.clientWidth - volumnBtnNode.offsetWidth);
			//保存进度条比率
			volumeSyncFlag = volumeRate;
			videoNode.volume = volumeRate;
			if(videoNode.volume == 0) {
				videoNode.muted = true;
				videoNode.volume = 0;
				addClass(volumeSwitch, "active");
			} else {
				//这里可以使用>0 && <1 做else if判断,也可以直接做else开启
				removeClass(volumeSwitch, "active");
				videoNode.muted = false;
			}
		}
	}
	dragFunc.dragger(volumnBtnNode, callBacks);

	//5.全屏显示
	//全屏flag
	var isFullScreen = false;
	fullScreenNode.onclick = function() {

		if(isFullScreen) {
			// 全屏 ---> 不是全屏 --> remove
			removeClass(fullScreen, "active");
			isFullScreen = false;
			if(document.exitFullscreen) {
				document.exitFullscreen();
			} else if(document.mozCancelFullScreen) {
				document.mozCancelFullScreen();
			} else if(document.webkitCancelFullScreen) {
				document.webkitCancelFullScreen();
			} else if(document.msExitFullscreen) {
				document.msExitFullscreen();
			}
		} else {
			addClass(fullScreen, "active");
			isFullScreen = true;
			var docElm = document.documentElement;
			//W3C  
			if(docElm.requestFullscreen) {
				docElm.requestFullscreen();
			}
			//FireFox  
			else if(docElm.mozRequestFullScreen) {
				docElm.mozRequestFullScreen();
			}
			//Chrome等  
			else if(docElm.webkitRequestFullScreen) {
				docElm.webkitRequestFullScreen();
			}
			//IE11
			else if(docElm.msRequestFullscreen) {
				docElm.msRequestFullscreen();
			}
		}
	}

	/*
	 * 工具类:class操作
	 */
	function addClass(node, className) {
		var reg = new RegExp("\\b" + className + "\\b");
		if(!reg.test(node.className)) {
			node.className += (" " + className);
		}
	}

	function removeClass(node, className) {
		if(node.className) {
			var reg = new RegExp("\\b" + className + "\\b");
			var classes = node.className;
			node.className = classes.replace(reg, "");
			if(/^\s*$/g.test(node.className)) {
				node.removeAttribute("class");
			}
		} else {
			node.removeAttribute("class");
		}
	}

	//转换时间格式
	function timeFormat(time) {
		//毫秒时间转换整数型
		time = parseInt(time);
		//向下取整
		var hour = addZero(Math.floor(time / 3600));
		//取余3600=秒,不能被取余的秒可以转换为分钟
		var minute = addZero(Math.floor(time % 3600 / 60));
		//不可向下取整,自动四舍五入,去round取消小数点
		var second = addZero(Math.round(time % 60));
		return hour + ":" + minute + ":" + second;

	}
	//时间补零函数
	function addZero(num) {
		var value = "";
		if(num < 10) {
			value = "0" + num;
		} else {
			value = value + num;
		}

		return value;
	}
})

6.html页面

<!DOCTYPE html>
<html>

	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no" />
		<title>一刀coder-视频播放器</title>
	</head>
	<link rel="stylesheet" href="css/22-video-player.css" />

	<body>
		<div id="wrap">
			<!--<h1>自定义播放器  一刀coder</h1>
			<hr />-->
			<!--请求本地视频拖拽效果异常,网络视频正常拖动
				线上视频地址:https://cevent-yameng-shop.oss-cn-beijing.aliyuncs.com/cubic-3D-camera-web%E5%85%A8%E6%A0%88%E7%89%87%E5%A4%B4.mp4
			-->
			<video src="video/cubic-3D-camera-web全栈片头_Trim2.mp4"></video>
			<div id="video-control">
				<!--1.视频开关-->
				<div class="video-btn">
					<span class="video-start"></span>
					<span class="video-stop"></span>
				</div>
				<!--2.视频进度条-->
				<div class="video-progress">
					<!--视频进度线及按钮-->
					<div class="progress-line">
						<div class="progress-btn"></div>
					</div>
					<!--当前进度条-->
					<div class="progress-current"></div>
				</div>
				<!--3.尾部模块-->
				<div class="video-other-operation">
					<!--3.1视频时间-->
					<div class="video-time">
						<span class="current-time"></span>/<span class="duration-time"></span>
					</div>
					<!--音量模块-->
					<div class="video-audio">
						<!--3.2音量开关-->
						<div class="audio-switch">
							<span></span>
						</div>
						<!--3.3音量控制按钮-->
						<div class="audio-volume">
							<!--3.4音量线及按钮-->
							<div class="volume-line">
								<div class="volume-btn"></div>
							</div>
							<!--3.5当前音量-->
							<div class="volume-current"></div>
						</div>
					</div>
					<!--3.6全屏按钮-->
					<div class="video-full-screen">
						<span></span>
					</div>
				</div>

			</div>
			<!--<hr />-->
		</div>
	</body>
	<script type="text/javascript" src="../6-bootstrap/js/jquery.min.js"></script>
	<script type="text/javascript" src="js/22-video-btn-drag.js"></script>
	<script type="text/javascript" src="js/22-video-player.js"></script>

</html>

7.效果图

显示全文