ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-06-18 17:03:19  阅读:128  来源: 互联网

标签:vue const 自定义 homeVideo 进度条 value width progressWidth


一,js代码:

<template>
<div>
  <div style="position:relative;">

  <video ref="homeVideo"
         style="position: absolute; width: 100vh; height: 100vw; left: -60vw; top:60vw;transform: rotate(90deg);"
         poster="static/video/cover.png" id="video"
         class="video" src="static/video/guotou.mp4" type="video/mp4"
         playsinline="true" webkit-playsinline="true"
         @canplay="getVideoInfo"
         @timeupdate="getCurrentInfo"
         x5-video-player-fullscreen="true" x5-video-orientation="portraint"
         loop="-1">
    <p>你的浏览器不支持video标签.</p>
  </video>

  <div id="controls" style="top:200px;width:100%;height:50px;background: rgb(255, 255, 0); position: absolute; z-index: 99;">
       <button @click="playOrPause">playOrPause</button>
       <button @click="openOrSlient">开关音量</button>
       <button @click="fullScreen">全屏</button>
       <div>
         总时长:{{duration}}
         当前位置:{{currentTime}}
       </div>

       <div style="width:100%;margin-left:10px;">
         <!-- 进度条容器 -->
         <div id="control" ref="control" class="control" @click="setProgress" @touchmove="controlMove" @touchend="controlEnd">
           <!-- 进度条本条 -->
           <div class="progress" :style="{background:'#00ff00', height:'10px',width: progressWidth+'px' }">
           </div>
             <!-- 滑块 -->
             <div class="slider_circle" :style="{left: (progressWidth-10)+'px' }" @touchstart="sliderStart" />
             <div class="slider_circle_large" :style="{left: (progressWidth - 25)+'px' }" @touchstart="sliderStart" />
         </div>
       </div>
  </div>

  </div>
</div>
</template>

<script>
import { ref } from "vue";

export default {
  name: "Video2Img",
  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();
        } else {
            homeVideo.value.pause();
        }
    }

    //开关音量
    const openOrSlient = () => {
      console.log("muted1:"+homeVideo.value.muted);
      if (homeVideo.value.muted == true) {
        homeVideo.value.muted = false;
      } else {
        homeVideo.value.muted = true;
      }
    }

    //全屏
    const fullScreen = () => {
      homeVideo.value.requestFullscreen();
    }

    //显示总时长
    const duration = ref(0);

    //得到视频的时长等信息
    const getVideoInfo = () => {
      //console.log(parseInt(homeVideo.value.duration)); // 101
      //console.log(formatTime(parseInt(homeVideo.value.duration))); // 01:41
      duration.value = formatTime(parseInt(homeVideo.value.duration));
    }

    //显示播放到的当前时间
    const currentTime = ref(0);

    //滑动到位置的宽度
    const progressWidth = ref(0);
    //得到视频当前播放到哪里的信息
    const getCurrentInfo = () => {
      // 视频已经播放时长
      currentTime.value = formatTime(parseInt(homeVideo.value.currentTime));

      //计算得到宽度:
      let ratio = homeVideo.value.currentTime / homeVideo.value.duration;
      //console.log("ratio:"+ratio);
      let allWidth = document.getElementById('control').getBoundingClientRect().width;
      //console.log("allwidth:"+allWidth);
      progressWidth.value = allWidth * 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 {left, width } = document.getElementById('control').getBoundingClientRect()
      // left: 进度条容器control到最左侧的距离
      //15: 按钮宽度的一半
      const proWidth = e.clientX - left
      progressWidth.value = proWidth;

      updadteCurrentTime(progressWidth.value, width);
    }

    //设置视频播放到指定的长度
    const updadteCurrentTime = (progressWidth, width) => {
      let dest = (progressWidth / width) *  homeVideo.value.duration;
      //console.log("dest:"+dest);
      homeVideo.value.currentTime = Math.floor(dest);
    }

    //移动的类型,用来标明是否在拖动进度条
    const moveType = ref("");
    //拖动开始时点击的位置
    const moveOffsetX = ref(0);
    //拖动开始时进度条的宽度
    const curWidth = ref(0);
    //当开始触摸开始在圆点按下时
    const sliderStart = (e) => {
        e.preventDefault();
      moveOffsetX.value = e.touches[0].clientX;
      moveType.value = "slider";
      curWidth.value = progressWidth.value;
    }

    //当触摸在controls上移动时
    const controlMove = (e) => {
      if (moveType.value !== 'slider') {
        return false;
      }
      e.preventDefault()
      // 滑动距离可视区域左侧的距离
      const X = e.touches[0].clientX
      //得到本次拖动已经过的距离
      const cl = X - moveOffsetX.value;
      //容器的宽度
      const {width } = document.getElementById('control').getBoundingClientRect()
      //得到已拖动到的宽度
      const ml =  curWidth.value + cl
      let proWidth
      if (ml <= 0) {
        //进度条长度最小和最大值的界定
        proWidth = 0
      } else if (ml >= width) {
        proWidth = width
      } else {
        proWidth = ml
      }
      progressWidth.value = proWidth;
      // 更新当前时间
      updadteCurrentTime(progressWidth.value, width);
    }

    //滑动结束
    const controlEnd = () => {
      moveType.value = "";
    }

    return {
      homeVideo,
      playOrPause,
      openOrSlient,
      fullScreen,
      getVideoInfo,
      duration,
      getCurrentInfo,
      currentTime,
      progressWidth,
      setProgress,
      //拖动
      sliderStart,
      controlMove,
      controlEnd,
    }
  }
}
</script>

<style scoped>
.control {
   width: calc(100% - 20px);
   background: #ff0000;
   height: 10px;
  position: relative;
}
.slider_circle {
  position: absolute;
  width:20px;
  height: 20px;
  border-radius: 10px;
  border: 1px;
  background: #0000ff;
  margin-top: -15px;
}

.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

 

标签:vue,const,自定义,homeVideo,进度条,value,width,progressWidth
来源: https://www.cnblogs.com/architectforest/p/16388708.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有