vue 中 自定义视频video

自定义视频进度条、音量、选集、全屏功能
利用HTML5 Audio/Video 事件给出的事件

<video :src= videoingurl ref="myvideo" @canplay="getTotal" @timeupdate="timeupdate"></video>

timeupdate:监控视频当前播放的时间控制进度条

timeupdate() {
  if(this.myvideo.currentTime == this.myvideo.duration){
    this.isPaused = !this.isPaused
    this.myvideo.pause()
  }
  this.currentTime = this.timeFormat(this.myvideo.currentTime)
  this.currentTimeVal = this.myvideo.currentTime
},

canplay:获取视频的总时长、进度条最大值

getTotal() {
   this.totalTime = this.timeFormat(this.myvideo.duration)
   this.durationProgress = this.myvideo.duration
 },

成品如下:
在这里插入图片描述
在这里插入图片描述

完整代码如下:

<div class="video-box" class="video-info-height">
 <video :src= videoingurl ref="myvideo" @canplay="getTotal" @timeupdate="timeupdate"></video>
  <div class="progress">
    <el-slider v-model="currentTimeVal" :max="durationProgress" :show-tooltip="false" @change="getNewTime"> </el-slider>
  </div>
  <div class="control">
    <i class="iconfonts" :class="isPaused ? 'iconzanting1' : 'iconicon_play'" @click="play()"></i>
    <span class="time">{{currentTime}} / {{totalTime}}</span>
    <i class="iconfonts iconyinliang-gao"></i>
    <el-slider v-model="volume" @change="getNewVoice"></el-slider>
    <span class="anthology">选集</span>
    <el-select v-model="videoingurl"  placeholder="请选择" @change="changevideo">
      <el-option
        v-for="item in videoinglist"
        :key="item.url"
        :label="item.channelDesc"
        :value="item.url"
      ></el-option>
    </el-select>
    <i class="iconfont iconquanping" @click="toggleFullScreen"></i>
  </div>
  <--以下内容是项目中需要播放其他类型内容,可自行绕过-->
  <div class="operating-room-video">
    <div class="lunb">
      <div class="sing" v-for="(i,index) in videochannalList" @click="clickvideosing(i,index)">
        <img v-show="currentIndex !== index" src="../../assets/images/videoimg.png" alt />
        <img v-show="currentIndex == index" src="../../assets/images/login_outer_bgi.png" alt />
        <p class="name">{{videochannalList[index][0].channelDesc}}</p>
      </div>
    </div>
  </div>
  
</div>
data() {
    return {
      volume: 30,       // 音量
      videochannalList: [], // 全部视频
      // 选集列表
      videoinglist: [
        {
          url: 'https://www.yy.com/ftpurl/medical-record/video/2020/07/01/1593596146146382.mp4',
          channelDesc: '导播'
        },
        {
          url: 'http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4',
          channelDesc: '导播'
        }
      ],
      videoingurl: '',           // 正在播放视频地址
      myvideo: '',   
      isPaused: false,        //标记当前的播放状态
      currentTime: '00:00',   //当前播放时间
      totalTime: '00:00',     //总时长
      currentTimeVal: 0,      // 进度条当前播放时间,必须是number类型
      durationProgress: 0,       // 进度条的最大值,必须是number类型
      currentIndex: '',           // 选中视频类型索引
    };
  },
mounted() {
     //获取播放器元素
    this.myvideo = this.$refs.myvideo
},
methods: {
	// 选集
    changevideo(val) {
      console.log(val)
      if(this.videoingurl == val) {
        this.isPaused = false
        this.myvideo.pause()
      }
    },
    play() {
      //修改当前的播放状态
      this.isPaused = !this.isPaused
      if(this.isPaused) {
        this.myvideo.play()
      }else {
        this.myvideo.pause()
      }
    },
    // 进度条拖动时间
    getNewTime(val) {
      console.log(val)
      this.myvideo.currentTime = val
    },
    // 音量控制
    getNewVoice(val) {
      this.volume = val
      let newVc = val / 100 //h5规定,volume的值必须再0-1之间,比如0.5就是50%的音量,但是进度条的值为100,因此这里做个除法
      this.myvideo.volume = newVc //赋值
    },
    //时间格式化处理
      timeFormat(time) {
        let minute = Math.floor((time % 3600) / 60)
        let second = Math.floor(time % 60)
        minute = minute < 10 ? "0" + minute : minute
        second = second < 10 ? "0" + second : second
        return `${minute}:${second}`
      },
      //获取总时长
      getTotal() {
        this.totalTime = this.timeFormat(this.myvideo.duration)
        this.durationProgress = this.myvideo.duration
      },
      //获取当前视频播放到的时间
      timeupdate() {
        if(this.myvideo.currentTime == this.myvideo.duration){
          this.isPaused = !this.isPaused
          this.myvideo.pause()
        }
        this.currentTime = this.timeFormat(this.myvideo.currentTime)
        this.currentTimeVal = this.myvideo.currentTime
      },
      //全屏切换
      toggleFullScreen(event) {
        const myvideo = this.$refs.myvideo
        //如果当前是全屏状态,就退出全屏,否则进入全屏状态
        //获取当前的全屏状态
        let isFullscreen = document.webkitIsFullScreen || document.fullscreen
        if(!isFullscreen) {
          const inFun = myvideo.requestFullscreen || myvideo.webkitRequestFullScreen
          //让当前播放器进入全屏状态
          inFun.call(myvideo)
        }else {
          const exitFun = document.exitFullscreen || document.webkitExitFullScreen
          //退出全屏状态要使用document
          exitFun.call(document)
        }
      },
}
    .video-box,
    .info-box {
      float: left;
      background: #fff;
      height: 5.1rem;
      box-sizing: border-box;
    }
    .video-box {
      width: 8.7rem;
      margin-right: 0.16rem;
      padding: 0.2rem;
      box-sizing: border-box;
      position: relative;
      video {
        width: 100%;
        height: 4.7rem;
        object-fit: cover;
        cursor: pointer;
      }
      .control {
        width: 8.3rem;
        height: 0.55rem;
        padding: 0.2rem;
        position: absolute;
        top: 4.35rem;
        left: 0.2rem;
        background-color: rgba(0, 0, 0, 0.2);
        display: flex;
        align-items: center;
        color: #fff;
        .iconicon_play{
          cursor:pointer;
        }
        /deep/.el-select .el-input .el-select__caret {
          color: #FFF;
        }
        /deep/.el-input__inner {
          color: #FFF;
          &::placeholder {
              color: #FFF;
          }
          &::-webkit-input-placeholder {
              /* WebKit browsers 适配谷歌 */
              color:#FFF;
          }
          &:-moz-placeholder {
              /* Mozilla Firefox 4 to 18 适配火狐 */
              color: #FFF;
          }
          &::-moz-placeholder {
              /* Mozilla Firefox 19+ 适配火狐 */
              color: #FFF;
          }
          &:-ms-input-placeholder {
              /* Internet Explorer 10+  适配ie*/
              color: #FFF;
          }
        }
        .time {
          margin-left: 0.22rem;
          color: #f5f5fa;
        }
        .iconyinliang-gao {
          margin-left: 2.68rem;
        }
        /deep/.el-input,
        div.el-select {
          width: 1.1rem !important;
          background-color: transparent;
          .el-input__inner {
            background-color: transparent;
          }
        }
        .anthology {
          margin: 0 0.2rem 0 0.24rem;
        }
        .iconquanping-video,.iconquanping {
          margin-left: 0.44rem;
          cursor:pointer;
        }
      }
      /deep/ .el-slider {
        width: 0.88rem;
        margin-left: 0.1rem;
        .el-slider__runway,
        .el-slider__bar {
          height: 0.04rem;
        }
        .el-slider__button {
          width: 0.13rem;
          height: 0.13rem;
        }
        .el-slider__button-wrapper {
          top: -16px;
        }
      }
      .progress {
        width: 8.3rem;
        position: absolute;
        top: 4.14rem;
        left: 0.2rem;
        overflow: hidden;
        .el-slider{
          width:100%;
          margin-left:0;
        }
      }
      .operating-room-video::-webkit-scrollbar { 
        // height: 4px;
        // background:#bababa;
      }
      .operating-room-video {
        width: 100%;
        height: 1.3rem;
        white-space:nowrap;
        overflow-x:auto; 
        overflow-y: hidden;
        > div.lunb{
          width: max-content;
          height: 1.2rem;
          > div.sing {
          width: 2.07rem;
          display: block;
          height: 1.2rem;
          float: left;
          position: relative;
          cursor: pointer;
          > img {
            width: 2.08rem;
            height: 1.2rem;
          }
          .name {
            width: 100%;
            position: absolute;
            bottom: 0;
            left: 0;
            background-color: rgba(0, 0, 0, 0.1);
            text-align: center;
            color: #fff;
          }
        }
        }
        
      }
    }
    .video-info-height {
      height: 6.3rem;
    }
    .info-box {
      width: 3.92rem;
      /deep/ .el-tabs__nav-scroll {
        display: flex;
        justify-content: space-around;
        .el-tabs__item {
          font-size: 0.18rem;
          padding: 0 0.5rem;
          color: #999;
        }
        .el-tabs__active-bar {
          width: 0.75rem !important;
          background-color: @color;
        }
        .is-active {
          color: #333;
        }
      }
      .video-info {
        padding: 0.1rem 0.4rem;
        > div {
          line-height: 0.34rem;
          display: flex;
          > div:first-child {
            color: @color;
            margin-right: 0.1rem;
            min-width: 0.7rem;
          }
          > div {
            display: inline-block;
          }
        }
      }
      .patient-info {
        > div {
          > div:first-child {
            min-width: 0.9rem;
          }
        }
      }
    }