当前位置:   article > 正文

如何封装个video插件。自定义进度条点击拖拽,播放暂停,播放倍速_vue video.js 自制进度条

vue video.js 自制进度条

问题:vue3开发嵌入式,播放器在浏览器中是正常的。但嵌入到app里,app不适配,无法全屏,无法设置倍速,controls在视频播放时点击视频无法弹出

1.是不是播放器问题导致不适配?

         期间试了vue-video-play,vue3-video-play等视频插件,也是相同情况

 2.网上没找到相关问题,自己搞吧

代码效果

  注意

1.使用了vant图标,先安装vant

2.视频链接,需要自己填

3.引入的useDraggable,就是封装的拖拽js

4.只适合移动端,因为到移动端有些问题,做了样式调整。动作事件也是移动端的

5.template中class类名不要乱改,封装的拖拽js代码里有获取

template代码

<template>

  <div class="all_box">

    <div class="videoBox">

      <video ref="videoPlayer"

        src=""></video>

    </div>

    <div class="controlsBox">

      <div class="progress-box" @click="onProgress($event)" ref="progressBox">

        <div class="progress" :style="{ width: `${progressLength}px` }"></div>

        <div ref="draggableDiv" class="it-layout-aside" :style="{ left: `${progressLength}px` }"></div>

      </div>

      <div class="playBtn" @click="clickPlay()">

        <van-icon name="pause-circle-o" size="30" v-if="showPlay" />

        <van-icon name="play-circle-o" size="30" v-else />

      </div>

      <div class="progress-time">{{ timeString }}</div>

      <div class="selRate">

        <select class="selRate_selet" v-model="selRate" @change="onSelRate()">

          <option value=0.5>0.5</option>

          <option value=1 selected>1.0</option>

          <option value=1.25>1.25</option>

          <option value=1.5>1.5</option>

          <option value=2>2.0</option>

        </select>

      </div>

    </div>

  </div>

</template>

script代码

<script setup>

import { ref, unref, } from "vue";

import { useDraggable } from './components/CommentResponse/Use'

const videoPlayer = ref(null);

const progressBox = ref(null)

const showPlay = ref(false)

const progressLength = ref(0)

const timeString = ref('00:00/00:00')

const selRate = ref(1)

//拖动进度条

const moveing = (val) => {

  showPlay.value = true;

  clearInterval(progressTimer)

  var length = val - progressBox.value.offsetLeft

  var percent = length / progressBox.value.offsetWidth

  unref(videoPlayer).currentTime = percent * unref(videoPlayer).duration

  unref(videoPlayer).play()

  progressTimer = setInterval(changeProgress, 60)

}

const draggableDiv = useDraggable(moveing)

//倍速

const onSelRate = () => {

  unref(videoPlayer).playbackRate = selRate.value

}

//启动|停止

const clickPlay = () => {

  if (showPlay.value) {

    unref(videoPlayer).pause();

    showPlay.value = false;

    clearInterval(progressTimer)

  } else {

    unref(videoPlayer).play();

    showPlay.value = true;

    progressTimer = setInterval(changeProgress, 60)

  }

}

var progressTimer = null // 进度 timer

// 计算时长,注意:这里的 padStart 是 es7 语法

const parseTime = (value) => {

  if (!value) return ''

  let interval = Math.floor(value)

  let minute = (Math.floor(interval / 60)).toString().padStart(2, '0')

  let second = (interval % 60).toString().padStart(2, '0')

  return `${minute}:${second}`

}

// 推进进度条

const changeProgress = () => {

  if (unref(videoPlayer).currentTime && unref(videoPlayer).duration) {

    if (parseTime(unref(videoPlayer).currentTime) === parseTime(unref(videoPlayer).duration)) {

      progressLength.value = 0;

      timeString.value = '00:00/00:00';

      showPlay.value = false;

    } else {

      let timeStr = parseTime(unref(videoPlayer).currentTime) + '/' + parseTime(unref(videoPlayer).duration)

      let percent = unref(videoPlayer).currentTime / unref(videoPlayer).duration

      progressLength.value = percent * 365;

      timeString.value = timeStr;

    }

  }

}

// 点击进度条的任意地方

const onProgress = (e) => {

  showPlay.value = true;

  clearInterval(progressTimer)

  var length = e.x - progressBox.value.offsetLeft

  var percent = length / progressBox.value.offsetWidth

  unref(videoPlayer).currentTime = percent * unref(videoPlayer).duration

  unref(videoPlayer).play()

  progressTimer = setInterval(changeProgress, 60)

}

</script>

css代码

<style scoped >

.all_box {

  margin: 30px;

}

.it-layout-aside {

  position: absolute;

  top: -4px;

  left: 0px;

  width: 13px;

  height: 13px;

  border-radius: 50%;

  background: rgb(0, 0, .5);

  opacity: 0.8;

  color: #fff;

  cursor: move;

  opacity: 1;

  z-index: 999;

}

video {

  width: 100%;

  height: 200px;

  margin: 0 auto;

  position: relative;

}

.controlsBox {

  background: #ccc;

  height: 50px;

  position: relative;

}

.progress-box {

  position: relative;

  background: rgba(0, 0, 0, 0.1);

  border-radius: 8px;

  overflow: hidden;

  cursor: pointer;

}

.progress {

  position: absolute;

  top: 0;

  left: 0;

  width: 0%;

  height: 100%;

  background: white;

  border-radius: 8px 0px 0px 8px;

}

.slider_circle {

  position: absolute;

  top: 0;

  left: 0;

  width: 20px;

  height: 50px;

  background: red;

}

.videoBox {

  width: 100%;

  min-width: 100%;

  max-width: 100%;

  height: 200px;

  position: relative;

  background: black;

}


 

.progress-box {

  width: 365px;

  height: 6px;

  position: absolute;

  bottom: 35px;

  right: 1%;

  overflow: visible;

}

.playBtn {

  width: 30px;

  height: 30px;

  position: absolute;

  bottom: 1px;

  left: 10px;

}

.progress-time {

  height: 30px;

  position: absolute;

  bottom: 1px;

  left: 50px;

  color: #f8f8f8;

  display: flex;

  align-items: center;

}

.selRate {

  width: 70px;

  height: 30px;

  position: absolute;

  bottom: 1px;

  left: 140px;

  display: flex;

  align-items: center;

  display: flex;

  align-items: center;

  justify-content: center;

}

.selRate_selet{

  height: 20px;

  width: 60px;

}

i {

  font-size: 40px;

  color: white;

}

</style>

封装的拖拽功能js

import { ref, unref, onMounted, onUnmounted } from "vue";

export const useDraggable = (moveing) => {

    // 声明一个 ref,用于存储 div 元素的引用

    const divRef = ref(null)

    // 声明一些变量,用于存储鼠标或触摸位置以及拖拽状态

    let offsetX = 0 // 鼠标点击或触摸点距离 div 左侧的偏移

    let offsetY = 0 // 鼠标点击或触摸点距离 div 顶部的偏移

    let isDragging = false // 是否正在拖拽中

    // 禁用页面滚动的函数

    const disablePageScroll = () => {

        document.body.style.overflow = 'hidden'

    }

    // 启用页面滚动的函数

    const enablePageScroll = () => {

        document.body.style.overflow = 'auto'

    }

    // 开始拖拽,禁用页面滚动

    const startDragging = () => {

        isDragging = true

        disablePageScroll()

    }

    // 停止拖拽,启用页面滚动,并稍后重新启用点击事件

    const stopDragging = () => {

        isDragging = false

        enablePageScroll()

        setTimeout(() => {

            if (divRef.value) {

                divRef.value.style.pointerEvents = 'auto'

            }

        }, 100)

    }

    // 处理鼠标移动或触摸移动事件

    const handleMouseMove = (event) => {

        requestAnimationFrame(() => {

            if (isDragging && divRef.value) {

                const clientX = 'touches' in event ? event.touches[0].clientX : event.clientX

                const clientY = 'touches' in event ? event.touches[0].clientY : event.clientY

                const x = clientX - offsetX

                const y = clientY - offsetY

                // 阻止事件传播,避免干扰正常滚动

                event.stopPropagation()

                event.preventDefault()

                // 获取浏览器窗口的最大可视区域宽度和高度

                // const maxX = window.innerWidth - (divRef.value.clientWidth || 0)

                const maxX = 360 - (divRef.value.clientWidth || 0)

                const maxY = window.innerHeight - (divRef.value.clientHeight || 0)

                // 设置 div 的位置,确保不超出窗口范围

                divRef.value.style.left = `${Math.min(maxX, Math.max(0, x))}px`

                // divRef.value.style.top = `${Math.min(maxY, Math.max(0, y))}px`

                divRef.value.style.top = `-4px`

                // 禁用 div 上的点击事件,以避免拖拽时触发点击事件

                divRef.value.style.pointerEvents = 'none'

                const tiao = document.querySelector('.progress')

                tiao.style.width = `${Math.min(maxX, Math.max(0, x))}px`

                // console.log(tiao.style, 111)

                //回调宽度

                moveing(Math.min(maxX, Math.max(0, x)))

            }

        })

    }

    // 处理鼠标松开或触摸结束事件

    const handleMouseUp = () => {

        // 停止拖拽,恢复点击事件

        stopDragging()

        // 移除鼠标移动事件和触摸移动事件的监听器

        document.removeEventListener('touchmove', handleMouseMove)

        document.removeEventListener('mousemove', handleMouseMove)

    }

    // 处理鼠标按下或触摸开始事件

    const handleMouseDown = (event) => {

        if (!divRef.value) return

        // 获取鼠标点击或触摸点相对于 div 左侧和顶部的偏移

        offsetX = 'touches' in event ? event.touches[0].clientX - divRef.value.offsetLeft : event.clientX - divRef.value.offsetLeft

        offsetY = 'touches' in event ? event.touches[0].clientY - divRef.value.offsetTop : event.clientY - divRef.value.offsetTop

        // 开始拖拽,添加鼠标移动和触摸移动事件监听器

        startDragging()

        document.addEventListener('mousemove', handleMouseMove, {

            passive: false, // 阻止默认滚动行为

        })

        document.addEventListener('touchmove', handleMouseMove, {

            passive: false, // 阻止默认滚动行为

        })

        // 添加鼠标松开和触摸结束事件监听器

        document.addEventListener('mouseup', handleMouseUp)

        document.addEventListener('touchend', handleMouseUp)

    }

    // 在组件挂载时,添加鼠标按下和触摸开始事件监听器

    onMounted(() => {

        if (divRef.value) {

            divRef.value.addEventListener('mousedown', handleMouseDown)

            divRef.value.addEventListener('touchstart', handleMouseDown)

        }

    })

    // 在组件卸载时,移除事件监听器

    onUnmounted(() => {

        if (divRef.value) {

            divRef.value.removeEventListener('mousedown', handleMouseDown)

            divRef.value.removeEventListener('touchstart', handleMouseDown)

        }

        document.removeEventListener('mouseup', handleMouseUp)

        document.removeEventListener('touchend', handleMouseUp)

    })

    // 返回 div 元素的引用,可以在组件中使用该引用来创建可拖拽的元素

    return divRef

}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/130222
推荐阅读
相关标签
  

闽ICP备14008679号