vue3实现video控件的h5端进度条拖拽与跳转

代码:

<template>
    <div class="video-box">
<!--            poster="static/video/covershu.png"-->
        <video
            ref="homeVideo"
            id="video"
            class="video"
            src="https://www.w3school.com.cn/i/movie.ogg"
            :playsinline="true"
            :webkit-playsinline="true"
            @canplay="getVideoInfo"
            @timeupdate="getCurrentInfo"
            @ended="handleEnd"
            @click="dispControls"
            loop
            :x5-video-player-fullscreen="true"
            x5-video-orientation="portraint"
        >
            <p>你的浏览器不支持video标签.</p>
        </video>
        <div id="controls"  class="controls">
<!--            pause play -->
            <van-icon
                :name="iconName"
                class="play-btn"
                @click="playOrPause"
                color="white"
            />
            <div class="slider">
                <!-- 进度条容器 -->
                <div
                    id="control"
                    ref="control"
                    class="control"
                    @click="setProgress"
                    @touchmove="controlMove"
                    @touchend="controlEnd"
                >
                    <!-- 进度条本条 -->
                    <div
                        class="progress"
                        :style="{width: progressWidth + 'px' }"
                    />
                    <!-- 滑块 -->
                    <div
                        v-if="progressWidth - 10 > 0"
                        class="slider_circle"
                        :style="{left: (progressWidth - 10) + 'px' }"
                        @touchstart="sliderStart"
                    />
                </div>
            </div>
            <span>
                {{currentTime }} / {{ duration}}
            </span>
        </div>
    </div>
</template>

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

//video的ref
const homeVideo = ref(null)
// 展厅或者播放
const iconName = ref('play')
//显示总时长
const duration = ref(0)
//显示播放到的当前时间
const currentTime = ref(0)

//滑动到位置的高度
const progressWidth = ref(0)
//移动的类型,用来标明是否在拖动进度条
const moveType = ref("")
//拖动开始时点击的位置
const moveOffsetX = ref(0)
//拖动开始时进度条的宽度度
const curWidth = ref(0)



//播放暂停
const playOrPause = () => {
    if (homeVideo.value.paused) {
        homeVideo.value.play()
        iconName.value = 'pause'
    } else {
        homeVideo.value.pause()
        iconName.value = 'play'
    }
}


//得到视频的时长等信息
const getVideoInfo = () => {
    duration.value = formatTime(parseInt(homeVideo.value.duration))
}

// 视频播放完毕
const handleEnd = () => {
    iconName.value = 'pause'
}
//得到视频当前播放到哪里的信息
const getCurrentInfo = () => {
    // 视频已经播放时长
    currentTime.value = formatTime(parseInt(homeVideo.value.currentTime))
    let ratio = homeVideo.value.currentTime / homeVideo.value.duration
    let allWidth = document.getElementById('control').getBoundingClientRect().width
    progressWidth.value = allWidth * ratio
}

// 格式化时间函数
const formatTime = (s) => {
    let t
    if (s > -1) {
        let hour = Math.floor(s / 3600)
        let min = Math.floor(s / 60) % 60
        let 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()
    progressWidth.value = e.clientX - left
    updadteCurrentTime(progressWidth.value, width)
}

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


//当开始触摸开始在圆点按下时
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 = ""
}


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'
    }
}
</script>

<style lang="less">
@import "index.less";
</style>

index.less文件:

.video-box {
    width:100%;
    height: 100vh;
    background-color: #000;
    .video {
        width: 100vw;
        height: 422px;
        margin-top: 200px;
    }
    .controls {
        width: 100vw;
        z-index: 1;
        display: flex;
        align-items: center;
        .play-btn {
            width: 30px;
            height: 30px;
            padding: 20px;
        }
        .progress {
            height: 7px;
            border-radius: 3px;
            background-color: #e4c487;
        }
        .slider {
            flex: 1;
            .control {
                width: 100%;
                background-color: white;
                padding: 20px 0;
                position: relative;
                background-clip: content-box;
                z-index: 2;
            }
        }
        span {
            color: white;
            font-size: 24px;
            padding: 0 20px;
        }
        .slider_circle {
            position: absolute;
            left: 0;
            top: 13px;
            width: 20px;
            height: 20px;
            border-radius: 10px;
            border: 1px;
            background: #e4c487;
        }
    }
}




效果图:

 

Vue Video.js是一个基于Vue.jsVideo.js的HTML5视频播放器组件,可以帮助我们快速搭建一个美观实用的视频播放器。在Vue Video.js中,要实现进度条拖动,需要做以下几个步骤: 1.首先,在Vue Video.js中,可以通过vjs-player组件来实现视频播放功能,我们需要给这个组件添加ref属性,以便在后面使用。 2.在vjs-player的mounted生命周期中,我们可以通过this.$refs.player来获取到video.js的player对象,然后通过player.on方法来监听时间变化事件。 3.在监听事件中,可以获取到当前播放的时间和视频总时长,从而计算出当前进度条的位置。同时,也可以监听进度条的mousedown和mousemove事件,来实现进度条拖动的功能。 4.最后,在进度条拖动结束的时候,需要通过player.currentTime()方法来设置视频的当前播放时间。 下面是相关代码片段: ```vue <template> <div> <vjs-player ref="player" :options="playerOptions"></vjs-player> <div class="progress-bar-wrap"> <div class="progress-bar" ref="progressBar" @mousedown="onProgressBarMouseDown($event)"> <div class="progress-bar-inner" :style="{width: progressWidth}"></div> <div class="progress-bar-thumb" :style="{left: progressWidth}"></div> </div> </div> </div> </template> <script> export default { data() { return { playerOptions: { autoplay: false, controls: true, sources: [{ src: 'https://example.com/path/to/video.mp4', type: 'video/mp4' }] }, progressWidth: 0, isDragging: false } }, mounted() { const player = this.$refs.player.$player player.on('timeupdate', () => { const currentTime = player.currentTime() const duration = player.duration() this.progressWidth = `${(currentTime / duration) * 100}%` }) document.addEventListener('mousemove', this.onDocumentMouseMove) document.addEventListener('mouseup', this.onDocumentMouseUp) }, beforeDestroy() { document.removeEventListener('mousemove', this.onDocumentMouseMove) document.removeEventListener('mouseup', this.onDocumentMouseUp) }, methods: { onProgressBarMouseDown(event) { this.isDragging = true this.onDocumentMouseMove(event) }, onDocumentMouseMove(event) { if (!this.isDragging) return const progressBar = this.$refs.progressBar const rect = progressBar.getBoundingClientRect() const progressWidth = ((event.clientX - rect.left) / rect.width) * 100 this.progressWidth = `${Math.min(Math.max(progressWidth, 0), 100)}%` }, onDocumentMouseUp() { if (!this.isDragging) return const player = this.$refs.player.$player const duration = player.duration() player.currentTime(duration * (parseInt(this.progressWidth) / 100)) this.isDragging = false } } } </script> <style> .progress-bar-wrap { width: 100%; height: 8px; background-color: #f2f2f2; } .progress-bar { position: relative; width: 100%; height: 100%; cursor: pointer; } .progress-bar-inner { position: absolute; top: 0; left: 0; height: 100%; background-color: #00bfff; } .progress-bar-thumb { position: absolute; top: -5px; left: -8px; width: 16px; height: 16px; border-radius: 50%; background-color: #00bfff; } </style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值