重写video标签实现的自定义播放器

2018-1-14 23:51:16 8,481 views

播放器

重写video标签实现的本地自定义播放器。

播放器样式

 
样式
进度条具体样式

语速具体样式
语速

实现的功能

1.播放本地视频文件
2.拖动进度条进行播放
3.定点播放
4.切换播放语速
5.动态调整音量
 

没实现的功能

视频全屏,可以自行修改

体验

想体验一下?戳这里==> http://www.suanliutudousi.com/player/index.html
若需要源码 链接: https://pan.baidu.com/s/1jJqLIse 密码: y76n
新增==》解决ie10,ie9不能播放的问题。将video的src地址换成本地的即可

源码部分

html代码

<!DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
    <link rel="stylesheet" type="text/css" href="//cdn.bootcss.com/font-awesome/4.2.0/css/font-awesome.min.css" />
    <link rel="stylesheet" href="//t99panzer.oss-cn-shanghai.aliyuncs.com/css/index.css" />
  </head>
  <body>
    <div class="mediaplayer">
      <div class="video">
        <video id="player" src="//t99panzer.oss-cn-shanghai.aliyuncs.com/video/Idina%20Menzel%20-%20Let%20It%20Go.mp4" autoplay="" poster="">
          你的浏览器太low了!!
          <input type="file" name="" id="" />
        </video>
      </div>
      <div class="wrap">
        <div class="progress-list">
          <div class="play-progress">
          </div>
          <!--进度条-->
        </div>
        <!--底层-->
        <div class="controls">
          <div class="left-box">
            <span id="video-btn"><i class="fa fa-pause"></i></span><span id="curtime">
              00:00:00</span><span class="left-box-div">/</span><span id="duration">
                00:00:00</span><span><label for="inputFile" id="upload-file"><i class="fa fa-upload"></i></label><input type="file" name="" id="inputFile" style="position: absolute;clip: rect(0,0,0,0);"/></span>
          </div>
          <!--左盒子-->
          <div id="box">
            <ul>
              <span id="slience"> <i class="fa fa-volume-up"></i></span><span class="volume_wrap voice-box">
                    <div class="voice-line"></div>
                  <div class="voice-volume"></div>
                  <div class="voice-btn"></div>
                   	    </span><span class="speed">
                正常
                <ul>
                  <li id="btn1">X1.0<i class='fa fa-check'></i></li>
                  <li id="btn2">X1.5</li>
                  <li id="btn3">X2.0</li>
                </ul>
              </span>
              <!--<span id="fullScreen" style="outline: none;"> <i class="fa fa-arrows-alt"></i></span>-->
              <!--全屏功能预留 #fullScreen margin-left:50px;-->
            </ul>
          </div>
          <!--右盒子-->
        </div>
      </div>
      <!--视频控制层-->
    </div>
    <!--播放器-->
    <script src="//apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="//t99panzer.oss-cn-shanghai.aliyuncs.com/js/Base.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="//t99panzer.oss-cn-shanghai.aliyuncs.com/js/main.js" type="text/javascript" charset="utf-8"></script>
  </body>
</html>

 

css代码

* {
  margin: 0;
  padding: 0;
}
/*整个容器*/
.fa {
  cursor: pointer;
  font-size: 24px;
  color: white;
}
.mediaplayer {
  margin: 0 auto;
  width: 960px;
  height: 576px;
  border: 2px solid #333;
}
.video {
  width: 960px;
  height: 530px;
}
/*控制组件容器*/
.wrap {
  position: absolute;
  width: 960px;
  height: 46px;
  background: #333;
}
/*视频资源层容器*/
#player {
  width: 100%;
  height: 100%;
}
/*---------------进度条层开始--------*/
/*进度条资源总长度层*/
.progress-list {
  transition-duration: .2s;
  position: absolute;
  width: 960px;
  height: 3px;
  top: -4px;
  margin-left: -1px;
  border: 1px solid black;
  border-radius: 3px;
  background: rgb(130, 130, 130);
}
/*进度条当前播放层*/
.play-progress {
  height: 3px;
  transition-duration: .2s;
  background-image: -webkit-linear-gradient(left, #57a900, #97ff00 80%, #dee2da);
  background-image: -ms-linear-gradient(left, #57a900, #97ff00 80%, #dee2da);
  background-image: -moz-linear-gradient(left, #57a900, #97ff00 80%, #dee2da);
  background-color: #D3D3D3\0;
  /*ie10以下兼容*/
}
.progress-list:hover {
  height: 13px;
}
.progress-list:hover .play-progress {
  height: 13px;
}
/*进度条层结束*/
/*组件具体盒子层 */
/*---------左盒子----------*/
/*暂停按钮*/
#curtime,
#duration,
.left-box-div {
  color: white;
}
#video-btn {
  display: inline-block;
  width: 22px;
  height: 22px;
  margin-right: 15px;
}
.left-box {
  width: 400px;
  float: left;
  margin-left: 40px;
}
.left-box span {
  margin-left: 5px;
}
#upload-file {
  margin-left: 15px;
}
/*----------------右盒子----*/
/*静音,全屏*/
#slience,
#fullScreen {
  display: inline-block;
  width: 22px;
  height: 22px;
  list-style: none;
  margin-left: 100px;
}
#box {
  width: 400px;
  float: right;
}
#box ul {
  vertical-align: middle;
}
#box ul ul li {
  list-style: none;
}
/*音量控制层*/
.voice-box {
  display: inline-block;
  position: relative;
  height: 30px;
  width: 124px;
  opacity: 0.7;
  line-height: 30px;
  top: 5px;
  margin-left: 5px;
  filter: alpha(opacity=70);
}
.voice-line {
  cursor: pointer;
  position: absolute;
  top: 13px;
  height: 4px;
  width: 124px;
  background: #ddd;
}
.voice-volume {
  position: absolute;
  top: 13px;
  height: 4px;
  width: 56px;
  cursor: pointer;
  background: #57a900;
}
.voice-btn {
  position: absolute;
  left: 56px;
  top: 9px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: white;
}
/*语速层开始*/
.speed {
  cursor: pointer;
  position: relative;
  display: inline-block;
  width: 44px;
  height: 22px;
  line-height: 22px;
  text-align: center;
  border: 1px solid black;
  background: #DAD6D8;
  margin-left: 25px;
  top: -2px
}
.speed:hover ul {
  visibility: visible;
}
/*滑动语速显示*/
.speed ul {
  visibility: hidden;
  background: #292929;
  position: absolute;
  top: -91px;
  left: -10px;
}
.speed li {
  cursor: pointer;
  color: white;
  font-family: arial;
  font-size: 16px;
  width: 70px;
  height: 30px;
  line-height: 30px;
}
.speed li:hover {
  background: grey;
}
/*语速层结束*/
.controls {
  height: 46px;
  line-height: 46px;
}

 

js核心代码

var base = new Base();
var player = document.getElementById("player"), //视频源
  btn = document.getElementById("video-btn"), //播放按钮
  btn1 = document.getElementById("btn1"), //倍速x1
  btn2 = document.getElementById("btn2"), //倍速x1.5
  btn3 = document.getElementById("btn3"), //倍速x2
  box = document.getElementById("box"), //视频控制层
  slience = document.getElementById("slience"), //静音
  full = document.getElementById("fullScreen"), //全屏
  curtime = document.getElementById("curtime"), //当前的播放长度
  duration = document.getElementById("duration"), //播放源的总长度
  inputFile = document.getElementById("inputFile"), //上传文件
  mediaplayer = base.getClass("document", "mediaplayer")[0], //整个播放器
  wrap = base.getClass("document", "wrap")[0], //控制层容器
  play_progress = base.getClass("document", "play-progress")[0], //播放时的进度条
  progress_width = base.getClass("document", "progress-list")[0], //进度条底层
  speed = base.getClass("document", "speed")[0], //速度层
  video = base.getClass("document", "video")[0],
  controls = base.getClass("document", "controls")[0], //组件控制层
  voice_btn = base.getClass("document", "voice-btn")[0], //音量按钮
  voice_box = base.getClass("document", "voice-box")[0], //音量盒子
  voice_line = base.getClass("document", "voice-line")[0], //音量底线
  voice_volume = base.getClass("document", "voice-volume")[0], //音量控制线
  curSpeed = base.getClass("document", "fa fa-check")[0]; //视频播放源容器
player.load(); //加载
//视频的元数据加,计算总时间
base.addHandler(player, "loadedmetadata", function() {
  var total = Math.floor(player.duration);
  total = base.formatTime(total);
  if(!isNaN(player.duration)) { //还没有加载时会为NaN
    play_progress.max = player.duration
    base.preventDefault(play_progress);
    duration.innerHTML = total;
  }
});
/*---------------- 进度条start-------------------*/
//拖动进度条
base.addHandler(progress_width, "click", function(event) {
  event = base.getEvent(event);
  var newCoor = base.getPageCoordinates(event).pageX,
    offLeft = mediaplayer.offsetLeft, //距左边的距离
    progress_list_width = progress_width.offsetWidth;
  curPlay = newCoor - offLeft; //拖到的新的位置
  var newLocation = curPlay / progress_list_width * player.duration;
  player.currentTime = newLocation;
});
//进度条滑动上浮
base.addHandler(progress_width, "mouseenter", function() {
  $(progress_width).animate({
    top: -14
  }, 0);
});
//进度条滑出上浮
base.addHandler(progress_width, "mouseleave", function() {
  $(progress_width).animate({
    top: -4
  }, 0);
});
/*---------------- 进度条end-------------------*/
/*---------------- 播放暂停按钮控制start-------------------*/
//屏幕点击
base.addHandler(player, "click", function(event) {
  if(player.paused) {
    player.play();
    btn.innerHTML = "<i class='fa fa-pause'></i>";
  } else {
    player.pause();
    btn.innerHTML = "<i class='fa fa-play'></i>";
  }
});
//按钮点击
base.addHandler(btn, "click", function(event) {
  if(player.paused) {
    player.play();
    btn.innerHTML = "<i class='fa fa-pause'></i>";
  } else {
    player.pause();
    btn.innerHTML = "<i class='fa fa-play'></i>";
  }
});
/*---------------- 播放暂停按钮控制end-------------------*/
/*---------------- 上传文件start-------------------*/
base.addHandler(inputFile, "change", function() {
  var reader = new FileReader(),
    files = this.files[0];
  reader.readAsDataURL(files);
  reader.onload = function(event) {
    var res = event.target.result;
    player.src = res;
    player.load(); //加载
    //本地文件加载时,播放新文件
    base.addHandler(player, "loadedmetadata", function() {
      if(player.paused) {
        player.play();
        btn.innerHTML = "<i class='fa fa-pause'></i>";
      }
    });
  }
});
/*---------------- 上传文件end-------------------*/
/*---------------- 音量静音start-------------------*/
player.volume = .5; //设置默认音量
//点击改变音量
var fn = function(event) {
  event = base.getEvent(event);
  var clientX = base.getPageCoordinates(event).pageX,
    ClientRect = base.getBoundingClientRect(voice_box).left, //相对于左边视口的距离
    volumeWidth = clientX - ClientRect;
  volumeWidth > voice_box.offsetWidth ? volumeWidth = voice_box.offsetWidth : volumeWidth;
  volumeWidth > 0 ? volumeWidth : volumeWidth = 0;
  voice_volume.style.width = volumeWidth + "px"; //音量宽度设置
  player.volume = (volumeWidth / voice_box.offsetWidth).toFixed(2);
  voice_btn.style.left = volumeWidth + "px";
  //音量游标控制
  switch(true) {
    case player.volume >= 0.5:
      slience.innerHTML = "<i class='fa fa-volume-up'></i>";
      break;
    case player.volume > 0:
      slience.innerHTML = "<i class='fa fa-volume-down'></i>";
      break;
    case player.volume == 0:
      slience.innerHTML = "<i class='fa fa-volume-off'></i>";
      break;
  }
  base.preventDefault(event);
};
base.addHandler(voice_box, "click", fn);
base.addHandler(voice_btn, "mousedown", function(event) {
  var boxOffset = base.getBoundingClientRect(voice_box).left;
  event = base.getEvent(event);
  var target = base.getTarget(event);
  document.onmousemove = function(event) { //因为这里是在document上移动的,所以需要在document上监听
    var event = base.getEvent(event);
    var oX = event.clientX - boxOffset; //鼠标点击的位置距离面板左边的距离
    var maxW = voice_box.offsetWidth;
    var minW = 0;
    oX > minW ? oX : oX = minW;
    oX > maxW ? oX = maxW : oX;
    target.style.left = oX + "px";
    voice_volume.style.width = oX + "px";
    player.volume = (oX / voice_box.offsetWidth).toFixed(2);
    switch(true) {
      case player.volume >= 0.5:
        slience.innerHTML = "<i class='fa fa-volume-up'></i>";
        break;
      case player.volume > 0:
        slience.innerHTML = "<i class='fa fa-volume-down'></i>";
        break;
      case player.volume == 0:
        slience.innerHTML = "<i class='fa fa-volume-off'></i>";
        break;
    }
  };
  document.onmouseup = function() {
    document.onmousemove = null; //删除移动事件
    document.onmouseup = null; //删除鼠标释放事件
  }
  base.preventDefault(event);
});
//静音及恢复
base.addHandler(slience, "click", function(event) {
  player.muted = !player.muted; //设置是否静音
  if(player.muted) {
    //静音时,设置音量盒,不需要设置player.volume
    voice_volume.style.width = 0 + "px";
    voice_btn.style.left = 0 + "px";
    slience.innerHTML = "<i class='fa fa-volume-off'></i>";
  } else {
    voice_volume.style.width = player.volume * voice_box.offsetWidth + "px";
    voice_btn.style.left = player.volume * voice_box.offsetWidth + "px";
    //		player.volume >= .5 ? slience.innerHTML = "<i class='fa fa-volume-up'></i>" : slience.innerHTML = "<i class='fa fa-volume-down'></i>";
    switch(true) {
      case player.volume >= 0.5:
        slience.innerHTML = "<i class='fa fa-volume-up'></i>";
        break;
      case player.volume > 0:
        slience.innerHTML = "<i class='fa fa-volume-down'></i>";
        break;
      case player.volume == 0:
        slience.innerHTML = "<i class='fa fa-volume-off'></i>";
        break;
    }
  }
});
base.addHandler(controls, "dragstart", function() {
  return false;
})
/*---------------- 音量静音end-------------------*/
/*---------------- 语速调节start-------------------*/
//更改播放速度
base.addHandler(btn1, "click", function(event) {
  event = base.getEvent(event);
  player.playbackRate = 1; //倍速为1
  speed.childNodes[1].style.visibility = "hidden";
  base.stopPropagation(event);
  speed.childNodes[0].nodeValue = "\u6b63\u5e38";
  if(btn1.innerHTML == "X1.0") {
    btn1.innerHTML = "X1.0<i class='fa fa-check'></i>";
    base.siblingNodes(btn1)[0].innerHTML = "X1.5"
    base.siblingNodes(btn1)[1].innerHTML = "X2.0"
  }
});
base.addHandler(btn2, "click", function(event) {
  event = base.getEvent(event);
  player.playbackRate = 1.5;
  speed.childNodes[1].style.visibility = "hidden";
  base.stopPropagation(event);
  speed.childNodes[0].nodeValue = "X1.5";
  if(btn2.innerHTML == "X1.5") {
    btn2.innerHTML = "X1.5<i class='fa fa-check'></i>";
    base.siblingNodes(btn2)[0].innerHTML = "X1.0"
    base.siblingNodes(btn2)[1].innerHTML = "X2.0"
  }
});
base.addHandler(btn3, "click", function(event) {
  event = base.getEvent(event);
  player.playbackRate = 2;
  speed.childNodes[1].style.visibility = "hidden";
  base.stopPropagation(event);
  speed.childNodes[0].nodeValue = "X2.0";
  if(btn3.innerHTML == "X2.0") {
    btn3.innerHTML = "X2.0<i class='fa fa-check'></i>";
    base.siblingNodes(btn3)[0].innerHTML = "X1.0"
    base.siblingNodes(btn3)[1].innerHTML = "X1.5"
  }
});
//得以触发下次滑动事件
base.addHandler(speed, "mouseenter", function() {
  speed.childNodes[1].style.cssText = "";
});
/*---------------- 语速调节end-------------------*/
/*---------------- 全屏start-------------------*/
base.addHandler(full, "click", function(event) {
  if(full.className == "") {
    //网页全屏
    mediaplayer.style.width = "100%";
    mediaplayer.style.height = "100%";
    full.className = "flag";
    progress_width.style.width = video.offsetWidth + "px"; //全屏时进度条
  } else if(full.className != "") {
    mediaplayer.style.width = 960 + "px";
    mediaplayer.style.height = 450 + "px";
    full.className = "";
    progress_width.style.width = video.offsetWidth + "px"; //正常情况进度条
  }
});
/*---------------- 全屏end-------------------*/
//定时更新当前时间
setInterval(function() {
    var cur = Math.floor(player.currentTime),
      med = mediaplayer.offsetWidth - 2,
      cur = base.formatTime(cur);
    curtime.innerHTML = cur;
    //播放完成
    if(player.ended === true) {
      player.pause();
      btn.innerHTML = "<i class='fa fa-play'></i>";
    }
    play_progress.style.width = player.currentTime * med / player.duration + "px";
  },
  0);

 

13

分享到微信朋友圈

打开微信,点击底部的“发现”,
使用“扫一扫”即可将网页分享至朋友圈。