video 自定义视频播放控件

这篇具有很好参考价值的文章主要介绍了video 自定义视频播放控件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ui设计的界面总是极具个性化的,要去修改插件中的视频控件的样式和布局太困难了,那就自己参照video原生事件,重写一个吧。

video控件,资讯,音视频,vue.js,前端,html5

(效果图预览)


一、video标签的属性(props)

 html <video>标签 | 菜鸟教程

<video 
     ref="videoPlayer" 
     id="videoElement" 
     controls 
     autoplay
     :muted="isMute" 
     width="800px" 
     height="600px" 
>
     您的浏览器不支持video
</video>

参数说明:(更多属性参照上述菜鸟教程中的video标签)

  • controls:默认为true,即向用户展示视频控件(如播放、暂停按钮等)
  • autoplay:如果出现该属性,则视频在就绪后马上播放。
  • muted:是否静音,默认为true
  • width:设置视频播放器的宽度

二、video视频控件的触发事件 

video标签支持的多媒体事件(Media Events) | 菜鸟教程

<video 
    ref="videoPlayer" 
    id="videoElement" 
    controls 
    autoplay
    :muted="isMute" 
    width="100%" 
    height="100%" 
    @loadeddata="setVideoPoster($event)"
    @progress="videoProgress($event)"
    @pause="videoPause($event)"
    @play="videoPlay($event)"
    @timeupdate="videoTimeUpdate()"
    @ended="videoEnded()"
    @contextmenu="contextmenu"
>
    您的浏览器不支持video
</video>

<button @click="handlePlay">播放</button>
<button @click="handlePause">暂停</button>
<button @click="handleMute">切换静音</button>
<button @click="fullScreen">全屏</button>

data(){
    return{
        isMute: true // 默认静音 
    }
}

1、播放(onplay事件)

this.$refs.videoPlayer.play();

methods:{
    // 视频要开始播放时
    videoPlay(e){
        // ...触发该函数后视频会开始播放,我们可以做一些想做的事情,比如改变自定义播放按钮的样式等
    },

    // 自定义播放按钮中,触发视频的播放事件
    handelPlay(){
        this.$refs.videoPlayer.play();   // 会触发videoPlay()函数
    }

}

2、暂停(onpause事件)

this.$refs.videoPlayer.pause();

methods:{
    // 视频要暂停播放时
    videoPause(e){
        // ...触发该函数后视频会暂停播放
    },

    // 自定义播放按钮中,触发视频的播放事件
    handelPause(){
        this.$refs.videoPlayer.pause();   // 会触发videoPause()函数
    }

}

3、静音(muted属性)

(1)切换静音

 // 手动切换静音(点击(非拖拽)静音时,用户选择的音量不变)

handleMute() {

      this.isMute = !this.isMute;

},

(2)改变音量(volume属性

this.$refs.videoPlayer.volume = a; (a为从 0~1的数字)

// 这里用element的进度条写音量大小调节条
<el-slider v-model="curVolume" :show-tooltip="false" @input="changeVolume"></el-slider>

data(){
    return{
        curVolume: 0, // 默认音量为0
    }
},

methods:{
    changeVolume(val){
        this.curVolume = val;
        // 由于h5规定volum的值在0-1之间,所以这里要对获取到的val做一个处理(滑块的val是从0-100)
        this.$refs.videoPlayer.volume = val / 100;
        
        // 音量为0的时候,video控件为静音
        if ( val == 0 ) {
           this.isMute = true;
        } else {
           this.isMute = false;
        }
    }
}

4、全屏

fullScreen() {
    this.$refs.videoPlayer.webkitRequestFullScreen();
},

5、播放进度条

获取视频总时长(duration

var videoObj = this.$refs.videoPlayer;

videoObj.addEventListener('canplay', () => {

        this.totalT = videoObj.duration;

})

获取视频加载进度

HTML5视频 - 加载百分比?

HTML5视频 - 加载百分比?

// 获取视频加载进度
videoProgress(e){
       var bf = this.$refs.videoPlayer.buffered;  
       var time = this.$refs.videoPlayer.currentTime;
       if ( bf.length != 0 ){
           var range = 0;
           while( !( bf.start(range) <= time && time <= bf.end(range) ) ) {
               range += 1;
           }
           var loadEndPercentage = ( bf.end(range) / this.playerVideo.duration ) * 100;  // 结束加载的百分比
           this.persentLoad = loadEndPercentage;
       }
},

(1)父组件调用

<template>
    <video 
      ref="videoPlayer" 
      @progress="videoProgress($event)"
      @timeupdate="videoTimeUpdate()"
    >
      您的浏览器不支持video
    </video>

    // 视频播放、加载进度条
    <ProgressLine 
      :presentT="presentT" 
      :totalT="totalT" 
      :persentLoad="persentLoad" 
      @changeCurrentTime="changeCurrentTime($event)"
      @changeCurrentWord="changeCurrentWord($event)"
    >
    </ProgressLine>

    // 播放时长、视频总时长
    <p>
      <span id="currentTime" ref="progressTimer">{{ videoCurrentTime }}</span>
      <span style="color: #ffffff;opacity: 0.3;">&nbsp;/&nbsp;</span>
      <span id="durationTime" ref="durationTimer">{{ videoTotalTime }}</span>
    </p>
</template>

import ProgressLine from './ProgressLine.vue';
export default {
    name: 'videoPage',
    components: {
        ProgressLine
    },
    data(){
        return{
            presentT: 0,  // 进度条的当前值,必须为number
            totalT: 0,    // 进度条的最大值,必须为number
            persentLoad: 0, // 视频加载进度 
            videoCurrentTime: '00:00', // 当前视频已播放时长
            videoTotalTime: '00:00',  // 视频总时长
        }
    },
    methods:{
        // 子组件传入的时间修改
        changeCurrentTime(data) {
            this.$refs.videoPlayer.currentTime = data;  // 点击进度条设置视频当前播放点
        },
        changeCurrentWord(data) {
            this.videoCurrentTime = this.formatTime(data);  // 当前播放时间显示文字
        },
        // 获取视频加载进度
        videoProgress(e){
            var bf = this.playerVideo.buffered;  
            var time = this.playerVideo.currentTime;
            if ( bf.length != 0 ){
                var range = 0;
                while( !( bf.start(range) <= time && time <= bf.end(range) ) ) {
                    range += 1; 
                }
                
                var loadEndPercentage = ( bf.end(range) / this.playerVideo.duration ) * 100;    // 结束加载的百分比
                this.persentLoad = loadEndPercentage;
            }
        },
        // 视频自动播放时
        videoTimeUpdate(){
            this.presentT = this.playerVideo.currentTime;   // 获取当前播放时长
            this.videoCurrentTime = this.formatTime(this.presentT);  // 时间格式化
        },
        // 时间格式化
        formatTime(t) {
            var m = parseInt(t % 3600 / 60)
            m = m < 10 ? '0' + m : m
            var s = parseInt(t % 60)
            s = s < 10 ? '0' + s : s
            return m + ':' + s
        },
    }
}

(2)进度条组件(播放进度条 和 加载进度条)

// ProgressLine.vue 进度条组件
<template>
    <div>
        <div class="line-background">
            <div class="time-line" @click="adjustProgress($event)">
                <div class="progress-round" ref="progressRound">
                    <div class="loading" ref="persentLoad" style="width: 0;"></div>   <!-- 加载进度条 -->
                    <div class="progress" ref="progress" @click="adjustProgress"></div>
                    <div class="round" ref="round" @mousedown="roundDrag"></div>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
export default {
    name: 'ProgressLine',
    props: {
        presentT: {},
        totalT: {},
        persentLoad: { default : 0 }
    },
    data() {
        return {
            // 进度条拖拽
            dragClick: false,
            // 鼠标/手指按下
            clickDown: false,
        }
    },
    created() {

    },
    watch: {
        // 侦听当前播放时长设置进度条
        presentT: {
            handler(newValue, oldValue) {
                // 未点击进度条
                if (this.dragClick == false && this.clickDown == false) {
                    this.$refs.progress.style.width = newValue / this.totalT * 100 + '%'
                    if ((newValue / this.totalT * 100 - 1.23) < 0) {
                        this.$refs.round.style.left = 0 + '%'
                    } else {
                        this.$refs.round.style.left = (newValue / this.totalT * 100) - 1.23 + '%'
                    }
                } else if (this.dragClick == true) {
                    this.dealWidth()
                    this.dragClick = false
                }
            }
        },
        persentLoad: {
            handler(newValue, oldValue) {
                this.$refs.persentLoad.style.width = ( newValue / 100 ) * 1300 + 'px'; 
            }
        }
    },
    methods: {
        progressData(data) {
            this.$emit('changeCurrentTime', data)
            this.$emit('changeCurrentWord', data)
        },
        // 进度条位置和圆点定位处理
        dealWidth() {
            this.$refs.progress.style.width = this.progressWidth / this.$refs.progressRound.offsetWidth * 100 + '%'
            if ((this.progressWidth / this.$refs.progressRound.offsetWidth * 100) - 1.23 < 0) {  // 圆点定位
                this.$refs.round.style.left = 0 + '%'
            } else {
                this.$refs.round.style.left = (this.progressWidth / this.$refs.progressRound.offsetWidth * 100) - 1.23 + '%'
            }
        },
        // 进度条点击
        adjustProgress(e) {
            this.dragClick = true
            e.preventDefault()
            const { left, width } = this.$refs.progressRound.getBoundingClientRect()  // 进度条到屏幕距离及进度条的宽度
            this.progressWidth = e.clientX - left
            if (this.progressWidth < 0) {//进度条边界值计算情况
                this.progressWidth = 0
            } else if (this.progressWidth >= width) {
                this.progressWidth = width
            } else {
                this.progressWidth = e.clientX - left // e.clientX:鼠标点击的位置到屏幕最左侧的距离
            }
            this.dealWidth()
            this.progressData((this.progressWidth / width) * this.totalT)
        },
        // 进度条圆点拖拽
        roundDrag(event) {
            event.preventDefault()
            const offsetX = event.offsetX
            this.dragClick = true
            this.clickDown = true  // 解决圆点拖拽进度条长度抖动
            document.onmousemove = (e) => {  // 给圆点添加移动事件
                e.preventDefault()// 阻止进度条拖拽时屏幕原有的滑动功能
                const X = e.clientX  // 获取圆点离屏幕的距离
                const { left, width } = this.$refs.progressRound.getBoundingClientRect()
                const ml = X - left  // 进度条长度:圆点离屏幕的距离减去进度条最左边离屏幕的距离
                if (ml <= 0) {  // 进度条长度最小和最大值的界定
                    this.progressWidth = 0
                } else if (ml >= width) {
                    this.progressWidth = width
                } else {
                    this.progressWidth = ml
                }
                this.progressData((this.progressWidth / width) * this.totalT)  //视频播放时间
                this.dealWidth()
            }
            // 抬起鼠标,结束移动事件
            document.onmouseup = () => {
                document.onmousemove = null
                document.onmouseup = null
                this.clickDown = false
            }
        },
    }
}
</script>
<style lang="less" scoped>
.line-background {
    width: 100%;
    height: 10px;
    background-color: rgba(255, 255, 255, 0.3);

    .time-line {
        width: 100%;
        height: 10px;
        background-color: #565651;

        .progress-round {
            cursor: pointer;
            width: 100%;
            position: relative;
            display: flex;

            .loading {
                height: 10px;
                background-color: rgba(255, 255, 255, 0.3);
            }

            .progress {
                position: absolute;
                top: 0;
                left: 0;
                width: 00%;
                height: 10px;
                background-color: #3d7eff;
            }

            .round {
                position: absolute;
                top: 50%;
                left: 0;
                transform: translateY(-50%);
                width: 16px;
                height: 16px;
                border-radius: 16px;
                background: #ffffff;
                box-shadow: -2px 0px 2px 2px rgba(3, 0, 0, 0.30);
            }
        }
    }
}
</style>

6、视频中禁用右键(可以禁止用户下载视频)

// 在视频中禁用右键(禁止用户下载)
contextmenu(e){
    e.returnValue = false;
},

7、设置倍速播放

 this.$refs.videoPlayer.playbackRate = rate;   // rate 一般在[2.0,1.75,1.5,1.0,0.75,0.5]范围文章来源地址https://www.toymoban.com/news/detail-782618.html

到了这里,关于video 自定义视频播放控件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue 视频播放插件vue-video-player自定义样式、自动播放设置、设置一开始全屏播放视频

    1、背景 项目中有涉及视频播放的需求,并且UI设计了样式,与原生的视频video组件有差异,所以使用了vue-video-player插件,并对vue-video-player进行样式改造,自定义播放暂停按钮、全屏按钮、时间进度条样式等,自动播放设置、设置一开始全屏播放视频、监听全屏事件等。 2、效

    2024年02月05日
    浏览(47)
  • 【音视频】如何播放rtsp视频流

    现阶段直播越来越流行,直播技术发展也越来越快。Webrtc和rtsp是比较火热的技术,而且应用也比较广泛。本文通过实践来展开介绍关于rtsp、webrtc的使用过程。 本文重点介绍如何播放rtsp视频流,通过ffplay方式以及VLC media player的方式来播放 可以参考上一篇博文:【音视频】基于

    2024年01月19日
    浏览(90)
  • 音视频 ffplay播放控制

    选项 说明 q, ESC 退出播放 f 全屏切换 p, SPC 暂停 m 静音切换 9, 0 9减少音量,0增加音量 a 循环切换音频流 v 循环切换视频流 t 循环切换字幕流 c 循环切换节目 w 循环切换过滤器或显示模式 s 逐帧播放 left/right 向后/向前拖动10秒 down/up 向后/向前拖动1分钟 鼠标右键单击 拖动与显

    2024年02月12日
    浏览(50)
  • 音视频项目—基于FFmpeg和SDL的音视频播放器解析(三)

    介绍 在本系列,我打算花大篇幅讲解我的 gitee 项目音视频播放器,在这个项目,您可以学到音视频解封装,解码,SDL渲染相关的知识。您对源代码感兴趣的话,请查看基于FFmpeg和SDL的音视频播放器 如果您不理解本文,可参考我的前一篇文章音视频项目—基于FFmpeg和SDL的音视

    2024年02月05日
    浏览(67)
  • Qt之基于QMediaPlayer的音视频播放器(支持常见音视频格式)

    Qt自带了一个Media Player的例子,如下图所示: 但是运行这个例子机会发现,连最基本的MP4格式视频都播放不了。因为QMediaPlayer是个壳(也可以叫框架),依赖本地解码器,视频这块默认基本上就播放个MP4,甚至连MP4都不能播放,如果要支持其他格式需要下载k-lite或者LAVFilter

    2024年02月02日
    浏览(67)
  • 使用Qt进行音视频播放

      Qt对音视频的播放和控制,相机拍照,收音机等多媒体应用提供了强大的支持。Qt5使用了全新的Qt Multimedia模块来实现多媒体应用,而原来Qt4中用于实现多媒体功能的Phonon模块已经被移除。   新的Qt Multimedia模块提供了丰富的接口,使读者可以轻松地使用平台的多媒体功

    2024年02月03日
    浏览(43)
  • 音视频 ffplay命令播放媒体

    播放本地文件 播放网络流 强制解码器 禁用音频或视频 播放YUV数据 播放RGB数据 播放PCM数据 推荐一个零声学院项目课,个人觉得老师讲得不错,分享给大家: 零声白金学习卡(含基础架构/高性能存储/golang云原生/音视频/Linux内核) https://xxetb.xet.tech/s/VsFMs

    2024年02月10日
    浏览(50)
  • iOS】AVPlayer 播放音视频

    iOS开发中不可避免地会遇到音视频播放方面的需求。 常用的音频播放器有 AVAudioPlayer、AVPlayer 等。不同的是,AVAudioPlayer 只支持本地音频的播放,而 AVPlayer 既支持本地音频播放,也支持网络音频播放。 常用的视频播放器有 MPMoviePlayerController、AVPlayer 等。不同的是,MPMoviePlay

    2024年02月14日
    浏览(46)
  • 音视频项目—基于FFmpeg和SDL的音视频播放器解析(二十一)

    介绍 在本系列,我打算花大篇幅讲解我的 gitee 项目音视频播放器,在这个项目,您可以学到音视频解封装,解码,SDL渲染相关的知识。您对源代码感兴趣的话,请查看基于FFmpeg和SDL的音视频播放器 如果您不理解本文,可参考我的前一篇文章音视频项目—基于FFmpeg和SDL的音视

    2024年02月02日
    浏览(72)
  • vue 视频播放插件vue-video-player自定义样式、自动播放设置、设置一开始全屏播放视频、监听全屏事件

    1、背景 项目中有涉及视频播放的需求,并且UI设计了样式,与原生的视频video组件有差异,所以使用了vue-video-player插件,并对vue-video-player进行样式改造,自定义播放暂停按钮、全屏按钮、时间进度条样式等,自动播放设置、设置一开始全屏播放视频、监听全屏事件等。 2、效

    2024年02月08日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包