• vue.js3: 自定义video垂直可拖动的进度条(vue@3.2.36)


    一,js代码

    <template>
      <div style="background: rgb(0, 0, 0);100%;height:100vh;">
        <div style="position:relative;">
    
          <video ref="homeVideo"
                 style="position: absolute;  100vw; height: 100vh; left:0;visibility:visible;"
                 poster="static/video/covershu.png" id="video"
                 class="video" src="static/video/guotoushu.mp4" type="video/mp4"
                 playsinline="true" webkit-playsinline="true"
                 @canplay="getVideoInfo"
                 @timeupdate="getCurrentInfo"
                 @click="dispControls"
                 x5-video-player-fullscreen="true" x5-video-orientation="portraint"
                 loop="-1">
            <p>你的浏览器不支持video标签.</p>
          </video>
    
          <div id="controls" style="background-image: linear-gradient(to right,black,transparent);40px;
    height:100vh; position: absolute; z-index: 99;"
    > <img ref="playButton" @click="playOrPause" src="static/svg/video-play.svg" style="transform:rotate(90deg);30px;height:30px;margin-top:10px;"/> <!-- <div> 总时长:{{duration}} 当前位置:{{currentTime}} </div> --> <div style="margin-top:15px; 5px; height: calc(100vh - 165px); margin-left: 17px;"> <!-- 进度条容器 --> <div id="control" ref="control" class="control" @click="setProgress" @touchmove="controlMove" @touchend="controlEnd"> <!-- 进度条本条 --> <div class="progress" :style="{background:'#ffffff', '5px',height: progressHeight+'px' }"> </div> <!-- 滑块 --> <div class="slider_circle" :style="{top: (progressHeight-10)+'px' }" @touchstart="sliderStart" /> <div class="slider_circle_large" :style="{top: (progressHeight - 25)+'px' }" @touchstart="sliderStart" /> </div> </div> <img ref="muteButton" @click="openOrSlient" src="static/svg/microphone.svg" style="transform:rotate(90deg);30px;height:30px;margin-top:20px;"/> <img @click="fullScreen" src="static/svg/full-screen.svg" style="transform:rotate(90deg);30px;height:30px;margin-top:10px;"/> </div> </div> </div> </template> <script> import { ref } from "vue"; export default { name: "Video3Img", components: { }, setup() { //video的ref const homeVideo = ref(null); //播放暂停 const playOrPause = () => { console.log("homeVideo.value.paused:"+homeVideo.value.paused); if (homeVideo.value.paused == true) { homeVideo.value.play(); playButton.value.src="static/svg/video-pause.svg"; } else { homeVideo.value.pause(); playButton.value.src="static/svg/video-play.svg"; } } //开关音量 const openOrSlient = () => { console.log("muted1:"+homeVideo.value.muted); if (homeVideo.value.muted == true) { homeVideo.value.muted = false; muteButton.value.src="static/svg/microphone.svg"; } else { homeVideo.value.muted = true; muteButton.value.src="static/svg/mute.svg"; } } //全屏 const fullScreen = () => { homeVideo.value.requestFullscreen(); } //显示总时长 const duration = ref(0); //得到视频的时长等信息 const getVideoInfo = () => { duration.value = formatTime(parseInt(homeVideo.value.duration)); } //显示播放到的当前时间 const currentTime = ref(0); //滑动到位置的高度 const progressHeight = ref(0); //得到视频当前播放到哪里的信息 const getCurrentInfo = () => { // 视频已经播放时长 currentTime.value = formatTime(parseInt(homeVideo.value.currentTime)); //计算得到高度: let ratio = homeVideo.value.currentTime / homeVideo.value.duration; //console.log("ratio:"+ratio); let allHeight = document.getElementById('control').getBoundingClientRect().height; //console.log("all"+allWidth); progressHeight.value = allHeight * ratio; //console.log("progressWidth:"+progressWidth.value); } // 格式化时间函数 const formatTime = (s) => { var t; if(s > -1) { var hour = Math.floor(s / 3600); var min = Math.floor(s / 60) % 60; var sec = s % 60; if(hour < 0 || hour == 0) { t = ''; } else if(0 < hour < 10) { t = '0' + hour + ":"; } else { t = hour + ":"; } if(min < 10) { t += "0"; } t += min + ":"; if(sec < 10) { t += "0"; } t += sec; } return t; } //设置进度条的长度 const setProgress = (e) => { e.preventDefault() // const {top, height } = document.getElementById('control').getBoundingClientRect() // top: 进度条容器control到最顶部的距离 const proHeight = e.clientY - top progressHeight.value = proHeight; updadteCurrentTime(progressHeight.value, height); } //设置视频播放到指定的长度 const updadteCurrentTime = (progressHeight, height) => { let dest = (progressHeight / height) * homeVideo.value.duration; //console.log("dest:"+dest); homeVideo.value.currentTime = Math.floor(dest); } //移动的类型,用来标明是否在拖动进度条 const moveType = ref(""); //拖动开始时点击的位置 const moveOffsetY = ref(0); //拖动开始时进度条的高度 const curHeight = ref(0); //当开始触摸开始在圆点按下时 const sliderStart = (e) => { e.preventDefault(); moveOffsetY.value = e.touches[0].clientY; moveType.value = "slider"; curHeight.value = progressHeight.value; } //当触摸在controls上移动时 const controlMove = (e) => { if (moveType.value !== 'slider') { return false; } e.preventDefault() // 滑动距离可视区域左侧的距离 const Y = e.touches[0].clientY //得到本次拖动已经过的距离 const cl = Y - moveOffsetY.value; //容器的高度 const {height } = document.getElementById('control').getBoundingClientRect() //得到已拖动到的高度 const ml = curHeight.value + cl let proHeight if (ml <= 0) { //进度条长度最小和最大值的界定 proHeight = 0 } else if (ml >= height) { proHeight = height } else { proHeight = ml } progressHeight.value = proHeight; // 更新当前时间 updadteCurrentTime(progressHeight.value, height); } //滑动结束 const controlEnd = () => { moveType.value = ""; } const playButton = ref(null); const muteButton = ref(null); const dispControls = () => { let isDisp = document.getElementById('controls').style.visibility; if (isDisp == 'hidden') { document.getElementById('controls').style.visibility = 'visible'; } else { document.getElementById('controls').style.visibility = 'hidden'; } } return { homeVideo, dispControls, playOrPause, playButton, muteButton, openOrSlient, fullScreen, getVideoInfo, duration, getCurrentInfo, currentTime, progressHeight, setProgress, //拖动 sliderStart, controlMove, controlEnd, } } } </script> <style scoped> .control { width: 5px; background: rgb(62,62,62); height: 100%; position: relative; } .slider_circle { position: absolute; width:20px; height: 20px; border-radius: 10px; border: 1px; background: #ffffff; /*margin-top: -15px;*/ left:-7px; opacity: 0.8; } .slider_circle_large { position: absolute; width:50px; height: 50px; border-radius: 25px; border: 1px; /*background: #00ffff;*/ opacity: 0.8; top: -20px; left:-20px; } </style>

    说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

             对应的源码可以访问这里获取: https://github.com/liuhongdi/
             或: https://gitee.com/liuhongdi

    说明:作者:刘宏缔 邮箱: 371125307@qq.com

    二,测试效果

    三,查看vue框架的版本:

    liuhongdi@lhdpc:/data/vue/imgtouch$ npm list vue
    imgtouch@0.1.0 /data/vue/imgtouch
    ├─┬ @vue/cli-plugin-babel@5.0.4
    │ └─┬ @vue/babel-preset-app@5.0.4
    │   └── vue@3.2.36 deduped
    ├─┬ element-plus@2.2.2
    │ ├─┬ @element-plus/icons-vue@1.1.4
    │ │ └── vue@3.2.36 deduped
    │ ├─┬ @vueuse/core@8.6.0
    │ │ ├─┬ @vueuse/shared@8.6.0
    │ │ │ └── vue@3.2.36 deduped
    │ │ ├─┬ vue-demi@0.13.1
    │ │ │ └── vue@3.2.36 deduped
    │ │ └── vue@3.2.36 deduped
    │ └── vue@3.2.36 deduped
    └─┬ vue@3.2.36
      └─┬ @vue/server-renderer@3.2.36
        └── vue@3.2.36 deduped
  • 相关阅读:
    myeclipse-9.0安装svn客户端插件
    jquery中lhgdialog插件(一)
    Jquery之ShowLoading遮罩组件
    git 命令
    org.apache.ibatis.builder.IncompleteElementException: Could not find parameter map
    在线压缩图片网址
    如何在知网下载外文文献
    Linux 常见命令
    在VIM 里面编辑和保存
    vi a.sh ABCD
  • 原文地址:https://www.cnblogs.com/architectforest/p/16389504.html
Copyright © 2020-2023  润新知