vue-cli中自定义播放器样式

<template>
    <div class="custom-video_container"
         ref="custom-video_container"
         @mouseover="handleControls($event, 'start')"
         @mouseleave="handleControls($event, 'end')">
        <video
                class="custom-video_video"
                ref="custom-video"
                :poster="videoOption.poster">

            <p>设备不支持</p>
        </video>

        <!-- 控制区域背景 -->
        <transition name="fade">
            <div class="custom-video_control"
                 v-show="!videoState.hideControl || !videoState.play">
                <div class="row1">
                    <!-- 进度条 -->
                    <div class="custom-video_control-bg"
                         @mouseleave="handlePrograssleave"
                         @mousedown="handlePrograssDown"
                         @mouseup="handlePrograssUp"
                         @mousemove="handlePrograssMove">
                        <div class="custom-video_control-bg-outside"
                             ref="custom-video_control-bg-outside">

                        <span
                                class="custom-video_control-bg-inside"
                                ref="custom-video_control-bg-inside">

                        </span>
                            <span
                                    class="custom-video_control-bg-inside-point"
                                    ref="custom-video_control-bg-inside-point"
                            ></span>
                        </div>
                    </div>
                </div>
                <div class="row2">
                    <div class="row2-left">
                        <!--播放按钮-->
                        <div class="custom-video-play-container">
                             <span
                                     class="custom-video_play custom-video_play-play icon_icon_video_paly"
                                     @click="play('btn')">
                             </span>
                            <span
                                    class="custom-video_play custom-video_play-pause icon_icon_video_suspend"
                                    @click="pause('btn')">
                            </span>
                        </div>
                        <!-- 时间 -->
                        <div class="custom-video_control-time">
                            <span>{
    
    {
    
    currentTime ? currentTime : '00:00'}}</span>
                            /
                            <span>{
    
    {
    
    duration ? duration : '00:00'}}</span>
                        </div>
                    </div>
                    <div class="row2-right">
                        <!-- 声音 -->
                        <div class="custom-video_control-voice"
                             @click="handelShowMultiple('in')"
                             @mouseleave="handelShowMultiple('out')">
                            <span class="custom-video_control-voice-play icon_icon_VMS_Set-up">
                                倍数
                            </span>
                            <ul v-show="voideoMultiple">
                                <li @click="changeMultiple(0.75)"
                                    :class="multipleIndex === 0.75 ? 'checkedMultiple': ''">0.75</li>
                                <li @click="changeMultiple(1)"
                                    :class="multipleIndex === 1 ? 'checkedMultiple': ''">1</li>
                                <li @click="changeMultiple(2)"
                                    :class="multipleIndex === 2 ? 'checkedMultiple': ''">2</li>
                            </ul>
                        </div>
                        <!--截图-->

                        <div class="custom-video_control-voice"
                             @click="handleScreenShot">
                              <span class="custom-video_control-voice-play  el-icon-camera-solid">
                                  截图
                            </span>
                        </div>


                        <!-- 全屏缩放 -->
                        <span
                                class="custom-video_control-full icon_icon_video_lessen"
                                @click="handleScreen"
                        ></span>
                    </div>
                </div>
            </div>
        </transition>
    </div>
</template>

<script>
  import flvjs from 'flv.js'
  import $http from '@/utils/$http'

  export default {
    
    
    name: 'videoRecordplayer',
    props: ['item'],
    data() {
    
    
      return {
    
    
        checkFull: false,
        isRecord: true,
        videoOption: {
    
    
          // src: require("../../static/media/taru.mp4"), //视频
          // poster: require("../../static/images/poster.jpg"), // 初始化占位图片
          volume: 20
        },
        videoState: {
    
    
          play: false, //播放状态
          hideControl: false, // 控制栏状态
          distance: 0, // 移动的距离
          downState: false, // 鼠标点击进度条
          playState: false,
          leftInit: 0, // 当前进度初始偏移量
          screenState: false
        },
        voiceState: {
    
     // 同上
          distance: 0,
          downState: false,
          topInit: 0
        },
        videoDom: null, // video
        videoProOut: null, // 视频总进度条
        videoPro: null, // 视频进度条
        videoPoi: null, // 视频进度点
        duration: 0, // 视频总时长
        currentTime: 0, // 视频当前播放时长
        processWidth: 0, // 视频进度条总长度
        voiceProOut: null, // 音频总进度条
        voicePro: null, // 音频进度条
        voicePoi: null, // 音频进度点
        volProcessHeight: 0,
        voideoMultiple: false, //播放倍数
        multipleIndex: 1
      }
    },
    created() {
    
    
      // console.log(this.item)
      window.addEventListener('resize', this.isFullScreen)
    },

    mounted() {
    
    
      this.toScreen()
      /*播放 流视频 的插件 如果是mp4格式 不需要 下载 - 引入 */
      const videoDom = this.$refs['custom-video']
      if (flvjs.isSupported) {
    
    
        this.flvPlayer = flvjs.createPlayer({
    
    
          type: 'flv',
          hasAudio: false,
          url: this.item.recordUrl
        })
        this.flvPlayer.attachMediaElement(videoDom)
        this.flvPlayer.load()
        this.flvPlayer.play()

      // 初始化相关元数据
      this.videoDom = this.$refs['custom-video']
      this.videoProOut = this.$refs['custom-video_control-bg-outside']
      this.videoPro = this.$refs['custom-video_control-bg-inside']
      this.videoPoi = this.$refs['custom-video_control-bg-inside-point']

      this.voiceProOut = this.$refs['custom-video_control-voice-bg-outside']
      this.voicePro = this.$refs['custom-video_control-voice-bg-inside']
      this.voicePoi = this.$refs['custom-video_control-voice-bg-point']

      this.processWidth = this.videoProOut.clientWidth

      this.videoDom.volume = this.videoOption.volume / 100 // 设置初始化声音
      this.initMedaData()

      }

    },


    methods: {
    
    


      initMedaData() {
    
     // 初始化video相关事件
        this.videoDom.addEventListener('loadedmetadata', () => {
    
     // 获取视频总时长
          this.videoState.leftInit = this.getOffset(this.videoProOut).left
          this.processWidth = this.videoProOut.clientWidth

          if (this.videoDom.duration !== Infinity) {
    
    
            this.duration = this.timeTranslate(this.videoDom.duration)
          } else {
    
    
            this.duration = '未知'
          }
        })
        this.videoDom.addEventListener('click', () => {
    
     // 点击视频区域可以进行播放或者暂停
          if (this.videoDom.paused || this.videoDom.ended) {
    
    
            if (this.videoDom.ended) {
    
    
              this.videoDom.currentTime = 0
            }
            this.play('btn')
          } else {
    
    
            this.pause('btn')
          }
        })
        this.videoDom.addEventListener('timeupdate', () => {
    
     // 监听视频播放过程中的时间
          const percentage = 100 * this.videoDom.currentTime / this.videoDom.duration
          this.videoPro.style.width = percentage + '%'
          this.videoPoi.style.left = percentage + '%'
          this.currentTime = this.timeTranslate(this.videoDom.currentTime)
        })
        this.videoDom.addEventListener('ended', () => {
    
     // 监听结束播放事件
          this.videoPro.style.width = 0
          this.videoPoi.style.left = 0
          this.currentTime = 0
          this.videoState.play = false
          this.videoState.hideControl = false
        })
        // this.videoDom.addEventListener('volumechange', () => {
    
    
        //   const percentage = this.videoDom.volume * 100
        //   this.voicePro.style.height = percentage + '%'
        //   this.voicePoi.style.bottom = percentage + '%'
        // })
      },
      play(flag) {
    
     // 播放按钮事件
        if (flag) this.videoState.playState = true
        this.videoState.play = true
        this.videoDom.play()
      },
      pause(flag) {
    
     // 暂停按钮事件
        if (flag) this.videoState.playState = false
        this.videoDom.pause()
        this.videoState.play = false
      },
      handlePrograssDown(ev) {
    
     // 监听点击进度条事件,方便获取初始点击的位置
        // 视频暂停
        this.videoState.downState = true //按下鼠标标志
        this.pause()
        this.videoState.distance = ev.clientX - this.videoState.leftInit
      },
      handlePrograssMove(ev) {
    
     // 监听移动进度条事件,同步播放相关事件
        if (!this.videoState.downState) return
        let disX = ev.clientX - this.videoState.leftInit
        if (disX > this.processWidth) {
    
    
          disX = this.processWidth
        }
        if (disX < 0) {
    
    
          disX = 0
        }
        this.videoState.distance = disX
        this.videoDom.currentTime = this.videoState.distance / this.processWidth * this.videoDom.duration
      },

      handlePrograssleave() {
    
    
        this.videoState.downState = false
      },
      handlePrograssUp() {
    
     //松开鼠标,播放当前进度条视频
        this.videoState.downState = false
        // 视频播放
        this.videoDom.currentTime = 2
        this.videoDom.currentTime = this.videoState.distance / this.processWidth * this.videoDom.duration
        this.currentTime = this.timeTranslate(this.videoDom.currentTime)
        // if (this.videoState.playState) {
    
    
        //   this.play()
        // }
      },

      handleControls(ev, flag) {
    
     // 监听离开或者进入视频区域隐藏或者展示控制栏
        switch (flag) {
    
    
          case 'start':
            this.videoState.hideControl = false
            break
          case 'end':
            this.videoState.hideControl = true
            break
          default:
            break
        }
      },
      handleScreen() {
    
     // 退出
        this.$emit('closeVideo')
      },
      timeTranslate(t) {
    
     // 时间转化
        let m = Math.floor(t / 60)
        m < 10 && (m = '0' + m)
        return m + ':' + (t % 60 / 100).toFixed(2).slice(-2)
      },
      getOffset(node, offset) {
    
     // 获取当前屏幕下进度条的左偏移量和又偏移量
        if (!offset) {
    
    
          offset = {
    
    }
          offset.left = 0
          offset.top = 0
        }
        if (node === document.body || node === null) {
    
    
          return offset
        }
        offset.top += node.offsetTop
        offset.left += node.offsetLeft
        return this.getOffset(node.offsetParent, offset)
      },

      //播放倍数
      handelShowMultiple(type) {
    
    
        if (type === 'in') this.voideoMultiple = true
        else this.voideoMultiple = false
      },

      //设置速度
      changeMultiple(speed) {
    
    
        this.videoDom.playbackRate = speed
        this.multipleIndex = speed
        this.voideoMultiple = false
      },

      //全屏的方法
      toScreen() {
    
    
        // console.log("全屏功能");
        let screenDom = this.$refs['custom-video_container']
        //W3C
        if (screenDom.requestFullscreen) {
    
    
          screenDom.requestFullscreen()
        }
        //FireFox
        else if (screenDom.mozRequestFullScreen) {
    
    
          screenDom.mozRequestFullScreen()
        }
        //Chrome等
        else if (screenDom.webkitRequestFullScreen) {
    
    
          screenDom.webkitRequestFullScreen()
        }
        //IE11
        else if (screenDom.msRequestFullscreen) {
    
    
          screenDom.msRequestFullscreen()
        }
      }
      ,

      isFullScreen() {
    
    
        let isFull = document.isFullScreen || document.mozIsFullScreen || document.webkitIsFullScreen
        // console.log(isFull)
        if (!isFull) this.$emit('closeVideo')
      }
      ,

      // 截图
      handleScreenShot() {
    
    
        // const video = document.querySelector("#splitDom-1");
        const video = this.$refs['custom-video']
        const canvas = document.createElement('canvas')
        const scale = 1
        canvas.width = video.videoWidth * scale
        canvas.height = video.videoHeight * scale
        canvas
          .getContext('2d')
          .drawImage(video, 0, 0, canvas.width, canvas.height)
        const base64src = canvas.toDataURL()
        // console.log(base64src)
        // 前端保存截图为jpg文件
        let obj = {
    
    
          'groupId': this.item.ipcGroupId,
          'ipcId': this.item.ipcId,
          'ipcName': `ZC-${
      
      this.item.recordId}-SCREENSHOT-${
      
      new Date().getTime()}`,
          'recordId': '',
          'streamUrl': base64src
        }
        $http.post('/manager/recording/storageScreenshots', obj).then(res => {
    
    
          if (res.status == 200) {
    
    
            this.$message({
    
    
              showClose: true,
              message: '截图保存成功',
              type: 'success'
            })
          }
        })
      }


    },

    beforeDestroy() {
    
    
      window.removeEventListener('resize', this.isFullScreen)
    }
  }
</script>

<style lang="scss" scoped>
    /* 总容器 */
    .custom-video_container {
    
    
        width: 500px;
        height: 300px;
        margin: 0 auto;
        position: relative;
        overflow: hidden;
    }

    /* 视频标签 */
    .custom-video_video {
    
    
        width: 100%;
        height: 100%;
        object-fit: fill;
    }

    .custom-video-play-container {
    
    
        width: 100px;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    /* 暂停 或者 播放 */
    .custom-video_play {
    
    
        display: inline-block;
        width: 50%;
        text-align: center;
        color: #f0f0f0;

    }

    /*!* 暂停隐藏 *!*/
    /*.custom-video_play-pause {*/
    /*display: none;*/
    /*}*/

    /*!* hover 显示 *!*/
    /*.custom-video_container:hover > .custom-video_play-pause {*/
    /*display: inline-block;*/
    /*}*/

    /* hover 播放按钮动画 */
    .custom-video_play:hover {
    
    
        box-shadow: 0 0 10px #5A4180;
        transition: all 0.4s;
    }

    /* 控制栏 */
    .custom-video_control {
    
    
        position: absolute;
        width: 100%;
        left: 0;
        bottom: 0;
        background-color: rgba(0, 0, 0, .55);
        display: flex;
        flex-direction: column;
        justify-content: space-between;
    }

    .row1 {
    
    
        height: 32px;
    }

    .row2 {
    
    
        height: 26px;
        display: flex;
        justify-content: space-between;
        padding-bottom: 10px;
    }

    .row2-left,
    .row2-right {
    
    
        display: flex;
    }

    /* 控制栏进度条 */
    .custom-video_control-bg {
    
    
        flex: 1;
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
        margin: 0 10px;
    }

    /* 控制栏进度条 —— 总长度 */
    .custom-video_control-bg-outside {
    
    
        width: 100%;
        height: 5px;
        border-radius: 2.5px;
        background-color: #aaa;
        position: relative;
        cursor: pointer;
    }

    /* 控制栏进度条 —— 播放长度 */
    .custom-video_control-bg-inside {
    
    
        position: absolute;
        display: inline-block;
        width: 0;
        height: 100%;
        border-radius: 2.5px;
        left: 0;
        top: 0;
        background-color: #fff;
        transition: all 0.2s;
    }

    /* 控制栏进度条 —— 播放点 */
    .custom-video_control-bg-inside-point {
    
    
        display: inline-block;
        width: 10px;
        height: 10px;
        background-color: #fff;
        border-radius: 50%;
        position: absolute;
        top: -2.5px;
        left: -1%;
        transition: all 0.2s;
    }

    /* 控制栏 —— 声音、时间、全屏缩放 */
    .custom-video_control-voice,
    .custom-video_control-time,
    .custom-video_control-full {
    
    
        display: flex;
        flex-direction: row;
        justify-content: center;
        align-items: center;
        color: #fff;
        position: relative;
        height: 100%;
    }

    .custom-video_control-voice:hover > .custom-video_control-voice-bg {
    
    
        display: block;
    }

    .custom-video_control-voice-play {
    
    
        z-index: 10;
    }

    .custom-video_control-voice-bg {
    
    
        display: none;
        position: absolute;
        width: 30px;
        height: 100px;
        background-color: rgba(0, 0, 0, .55);
        left: 0;
        bottom: 0px;
        border-radius: 15px;
    }

    .custom-video_control-voice-bg-outside {
    
    
        width: 5px;
        height: 70px;
        border-radius: 2.5px;
        background-color: #aaa;
        position: absolute;
        left: 50%;
        transform: translate3d(-50%, 10%, 0);
        cursor: pointer;
    }

    .custom-video_control-voice-bg-inside {
    
    
        display: inline-block;
        position: absolute;
        width: 100%;
        bottom: 0;
        left: 0;
        border-radius: 2.5px;
        background-color: #fff;
        height: 0;
    }

    .custom-video_control-voice-bg-point {
    
    
        display: inline-block;
        width: 10px;
        height: 10px;
        background-color: #fff;
        border-radius: 50%;
        position: absolute;
        left: -2.5px;
        bottom: -1px;
    }

    .custom-video_control-time {
    
    
        font-size: 12px;
    }

    .custom-video_control-full {
    
    
        font-size: 14px;
    }

    .custom-video_control-voice,
    .custom-video_control-full {
    
    
        /*width: 30px;*/
        height: 30px;
        margin: 0 10px;
        cursor: pointer;
    }

    /* 控制栏隐藏动画 */
    .fade-enter-active {
    
    
        transition: all .3s ease;
    }

    .fade-leave-active {
    
    
        transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
    }

    .fade-enter, .fade-leave-to {
    
    
        transform: translateY(50px);
        opacity: 0;
    }

    /* 倍数 */
    ul {
    
    
        position: absolute;
        bottom: 25px;
        width: 100%;
        text-align: center;
        background: rgba(255, 255, 255, 0.1);
        border-radius: 4px;
        padding: 0 10px;
    }

    ul > li {
    
    
        height: 35px;
        line-height: 35px;
    }

    .checkedMultiple {
    
    
        color: #328cfa;
    }
</style>

猜你喜欢

转载自blog.csdn.net/weixin_43413047/article/details/106551138