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

开发者在使用Vue3开发嵌入式视频播放器时遇到在App中无法全屏、设置倍速和点击controls失效的问题。文章探讨了可能的原因,包括视频插件选择和移动端适配,并提供了相关代码片段和解决思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题: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

}

<think>嗯,用户的问题是关于网页视频进度条无法拖动以及如何设置倍速播放的。首先,我需要回忆一下之前收集的参考资料,看看有没有相关的解决方法。根据引用[2]和引用[3],我记得有两种方法:一种是使用浏览器的开发者工具手动调整视频进度,另一种是通过JavaScript代码加速播放或者跳过部分内容。另外,引用[5]提到了使用vue-video-player插件封装视频组件,这可能适用于前端开发的情况。 首先,用户可能遇到的是网页视频被设计成无法拖动进度条的情况,这可能是因为网站为了防止用户跳过某些内容,比如广告或者重要部分。这时候,开发者工具的方法可能有效,因为它允许用户直接修改视频元素的currentTime属性,从而改变播放进度。不过,这种方法需要用户有一定的技术背景,知道如何打开控制台和执行代码。 然后,关于倍速播放的问题,引用[3]提供了一个JavaScript函数,通过设置video元素的playbackRate属性来加速视频。这种方法虽然有效,但可能需要用户定期执行,因为有些网站可能会检测并重置播放速度。另外,引用[4]和引用[5]分别提到了微信小程序和Vue框架中的实现方式,这可能对开发者更有帮助,但普通用户可能更倾向于使用浏览器扩展或者脚本工具,比如Tampermonkey来注入这些代码。 接下来,我需要将这些方法整理成步骤,确保用户能够理解并操作。对于普通用户来说,使用开发者工具可能有些复杂,但分步骤说明应该没问题。同时,建议用户安装脚本管理器来简化过程,这样他们就不需要每次手动输入代码了。 另外,还需要考虑不同网站的反制措施,比如有些网站可能会检测到playbackRate的变化并自动恢复,因此可能需要定时执行加速代码,如引用[3]中提到的setInterval函数。此外,用户需要注意,某些网站可能有使用条款限制修改播放行为,需遵守相关规定。 最后,总结一下解决方法,分为手动调整和自动化脚本两种,同时提供前端开发的解决方案,供不同需求的用户选择。确保回答结构清晰,步骤详细,并引用相关的参考资料作为支持。</think>### 解决网页视频进度条无法拖动及设置倍速播放的方法 #### 一、进度条无法拖动的解决方法 1. **通过浏览器开发者工具手动调整** - 打开浏览器开发者模式(按 `F12` 或右键选择“检查”),切换到 `Console`(控制台)标签。 - 输入以下代码并执行,直接修改视频当前播放时间: ```javascript document.querySelector('video').currentTime = 120; // 将120替换为目标秒数 ``` 此方法可绕过前端限制,强制调整播放进度[^2]。 2. **使用自动化脚本跳过限制** - 安装浏览器脚本管理器(如 `Tampermonkey`),添加以下脚本: ```javascript // ==UserScript== // @name Video Control Unlock // @description 解除视频进度条限制 // @match *://*/* // ==/UserScript== let video = document.querySelector('video'); if (video) { video.controls = true; // 强制显示控制条 video.removeAttribute('controlslist'); // 移除属性限制 } ``` 此脚本可恢复被隐藏的进度条控制功能。 #### 二、设置倍速播放的方法 1. **通过控制台直接加速** 在开发者工具控制台中执行: ```javascript document.querySelector('video').playbackRate = 2.0; // 2.0为倍率,可调整 ``` 此方法适用于临时加速,但可能被网站脚本重置[^3]。 2. **定时注入加速脚本** 使用以下代码持续强制加速: ```javascript setInterval(() => { let videos = document.getElementsByTagName('video'); for (let v of videos) { v.playbackRate = 16.0; // 设置16倍速 v.play(); // 防止暂停 } }, 1000); ``` 该脚本通过定时器覆盖网站的限制逻辑。 3. **前端框架集成方案(开发者适用)** 若使用 `Vue` 等框架,可通过 `vue-video-player` 插件封装组件: ```javascript // 安装插件 npm install vue-video-player -S // 组件配置 <template> <video-player :options="playerOptions" @ready="onPlayerReady"/> </template> <script> export default { methods: { onPlayerReady(player) { player.playbackRate(2.0); // 初始2倍速 } } } </script> ``` 此方法支持自定义控制逻辑,避免被网站限制[^5]。 #### 三、注意事项 - 部分网站会检测 `playbackRate` 修改行为,需配合反检测代码(如重写原生方法)。 - 微信小程序需使用 `VideoContext` API 控制倍速[^4]。 - 遵守平台使用条款,避免因绕过限制导致账号风险。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值