原生h5+css3 实现简单视频播放器组件

视频播放器组件案例

实现效果

等待图片
效果1效果2

实现功能

  • 全屏切换
  • 进度条点击跳播
  • 音量点击设置大小

涉及知识点

  • video对象属性

    • .duration 获取视频总长度(秒)
    • .currentTime 当前播放时间(秒)
    • .volume 获取音量或设置音量 (值0-1)
    • .paused 是否暂停状态 (true/false)
  • video 对象方法

    • .play() 播放
    • .pause() 暂停
  • video 对象事件

    • .oncanplay 视频资源可以播放时触发

    • .ontimeupdate 视频播放过程中或时间更改时触发

    • .onended 视频播放完毕后

  • 注意点

    • 进度条(音量控制条) 由3层div组成,控制层,当前时间层和总时长层,叠加在一起,最上层用来点击触发事件
    • 火狐上无法监控oncanplay()方法,暂未解决 。在谷歌上运行效果OK

案例代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link href="//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <title>自定义视频播放器</title>
    <style>
        *{box-sizing: border-box}
        .player{
            width:970px;
            height:670px;
            margin:0 auto;
            background-color: #222;
            padding:10px;
            -moz-user-select:none; /* Firefox私有属性 */
            -webkit-user-select:none; /* WebKit内核私有属性 */
            -ms-user-select:none; /* IE私有属性(IE10及以后) */
            -khtml-user-select:none; /* KHTML内核私有属性 */
            -o-user-select:none; /* Opera私有属性 */
            user-select:none; /* CSS3属性 */
        }
        .show{
            text-align: center;
            height: 600px;
            background: #333;
            background:url('./public/images/loading.gif') center center;
            background-size: contain;
        }
        video{
            display: none;
            width:auto;
            max-width: 100%;
        }

        .controller{
            color:#fff;
            padding:15px 0;
        }
        .controller_tool{
            float:left;
            text-align: center;
            cursor:pointer;
        }
        .player_btn{
            width:50px;
        }
        .pull_btn{
            float:right;
            width:50px;
        }
        .progress{
            height:6px;
            border-radius: 2px;
            margin-top:8px;
        }
        .total_progress{
            width:650px;
            background-color:#666;
        }
        .current_progress{
            position:absolute;
            width:0px;
            background-color:yellowgreen;
        }
        .bar{
            position:absolute;
            width:650px;
            z-index: 99;
        }
        .time_box{
            margin-left:15px;
            cursor:default;
        }
        .volume_box{
            position:relative;
            width:40px;
            padding:0 10px;
        }
        .volume_proress_now {
            border-radius: 4px;
            top:-30px;
            left:16px;
            position:absolute;
            width:6px;
            height:30px;
            background-color: yellowgreen;
        }
        .volume_proress{
            border-radius: 4px;
            top:-60px;
            left:16px;
            position:absolute;
            width:6px;
            height:60px;
            background-color: #666;
        }
        .volume_proress_bar{
            border-radius: 4px;
            top:-60px;
            left:16px;
            position:absolute;
            width:6px;
            height:60px;
        }
        .volume_bar_box{
            display: none;
        }
    </style>
</head>
<body>
<main>
    <div class="player">
        <div class="show">
            <video id="my_video" height="100%" src="./public/media/1.mp4"></video>
            <div class="loading"></div>
        </div>
        <div class="controller">
            <div class="controller_tool player_btn"><i class="fa fa-play" aria-hidden="true"></i></div>
            <div class="controller_tool player_progress">
                <div class="progress bar"></div>
                <div class="progress current_progress"></div>
                <div class="progress total_progress"></div>
            </div>
            <div class="controller_tool time_box">
                <span id="current_time">00:00:00</span>
                /
                <span id="total_time">00:00:00</span>
            </div>
            <div class="controller_tool volume_box">
                <div class="volume_bar_box">
                    <div class="volume_proress"></div>
                    <div class="volume_proress_now"></div>
                    <div class="volume_proress_bar"></div>
                </div>
                <i class="fa fa-volume-up" aria-hidden="true"></i>
            </div>
            <div class="controller_tool pull_btn"><i class="fa fa-arrows-alt" aria-hidden="true"></i></div>
        </div>
    </div>
</main>
<script>
    window.onload=function(){
        var video = document.querySelector('#my_video');
        //视频可以播放时,初始化控制面板上的数据
        video.oncanplay=function(){
            //默认为等待图标 显示视频内容
            video.style.display='inline-block';
            //设置默认音量
            video.volume = 0.5;
            //获取视频总时长
            var total_time=formatTime(video.duration);
            document.querySelector('#total_time').innerHTML=total_time;
        };

        //视频在播放过程中更改播放进度条
        video.ontimeupdate = function(){
            var current_time = video.currentTime;
            var total_time = video.duration;
            document.querySelector('#current_time').innerHTML=formatTime(current_time);
            //进度百分比
            var w=document.querySelector('.total_progress').clientWidth;
            document.querySelector('.current_progress').style.width=(current_time/total_time)*w+'px';
        }

        //播放完毕的时候,把播放时间回到初始位置
        video.onended = function(){
            video.currentTime = 0;
            document.querySelector('.player_btn i').classList.remove('fa-stop');
            document.querySelector('.player_btn i').classList.add('fa-play');
        }


        //点击进度条进行跳播
        document.querySelector('.bar').onclick=function(e){
            //获取总长度
            var w = this.clientWidth;
            //获取鼠标偏移量
            var c_w = e.offsetX;

            //根据偏移量获取总时间的百分比
            var now_time = video.duration * (c_w/w);
            video.currentTime = now_time;

        }

        //控制音量组件显示/隐藏
        document.querySelector('.fa-volume-up').onclick = function(e){
            if(this.classList.contains('active')){
                this.classList.remove('active');
                document.querySelector('.volume_bar_box').style.display='none';
            }else{
                this.classList.add('active');
                document.querySelector('.volume_bar_box').style.display='block';
            }

            //阻止冒泡事件
            e.stopPropagation();
            e.preventDefault();
        }

        //收起音量设置控制条
        document.onclick = function(){
            document.querySelector('.fa-volume-up').classList.remove('active');
            document.querySelector('.volume_bar_box').style.display='none';
        }

        //设置音量大小
        document.querySelector('.volume_proress_bar').onclick = function(e){
            var h = this.clientHeight;
            var c_h=h-e.offsetY;
            //设置音量
            video.volume = c_h/h;
            //设置对应的音量高度
            document.querySelector('.volume_proress_now').style.height=c_h+'px';
            document.querySelector('.volume_proress_now').style.top=-c_h+'px';
            e.stopPropagation();
            e.preventDefault();
        }

        // 点击播放时
        document.querySelector('.player_btn').onclick=function(){
            if(video.paused){
                video.play();
                document.querySelector('.player_btn i').classList.remove('fa-play');
                document.querySelector('.player_btn i').classList.add('fa-stop');
            }else{
                video.pause();
                document.querySelector('.player_btn i').classList.remove('fa-stop');
                document.querySelector('.player_btn i').classList.add('fa-play');
            }
        }

        //全屏切换
        document.querySelector('.pull_btn').onclick=function(){
            var player=document.querySelector('.player');
            var flag = document.fullscreenElement || document.webkitFullscreenElement ||document.mozFullScreenElement ||document.msFullscreenElement ||document.oFullscreenElement;

            if(flag){//全屏状态
                //兼容性问题
                if(document.cancelFullScreen){
                    document.cancelFullScreen();
                }else if(document.webkitCancelFullScreen){//chome
                    document.webkitCancelFullScreen();
                }else if(document.mozCancelFullScreen){//fox
                    document.mozCancelFullScreen();
                }else if(document.msCancelFullScreen){//ie
                    document.msCancelFullScreen();
                }else if(document.oCancelFullScreen){//opera
                    document.oCancelFullScreen();
                }

                //窗口大小设置
                document.querySelector('.show').style.height=600+'px';
                document.querySelector('.total_progress').style.width=650+'px';

                //切换图标
                document.querySelector('.pull_btn i').classList.remove('fa-compress');
                document.querySelector('.pull_btn i').classList.add('fa-arrows-alt');
            }else{
                //兼容性问题
                if(player.requestFullScreen){
                    player.requestFullscreen();
                }else if(player.webkitRequestFullScreen){//chome
                    player.webkitRequestFullScreen();
                }else if(player.mozRequestFullScreen){//fox
                    player.mozRequestFullScreen();
                }else if(player.msRequestFullScreen){//ie
                    player.msRequestFullScreen();
                }else if(player.oRequestFullScreen){//opera
                    player.oRequestFullScreen();
                }
                //窗口大小设置
                document.querySelector('.show').style.height=window.outerHeight-40+'px';
                document.querySelector('.total_progress').style.width=window.innerWidth-350+'px';
                //切换图标
                document.querySelector('.pull_btn i').classList.remove('fa-arrows-alt');
                document.querySelector('.pull_btn i').classList.add('fa-compress');
            }
        }

        //解决esc或h5全屏自带的退出无法恢复原大小问题
        window.onresize=function() {
            var flag = document.fullscreenElement || document.webkitFullscreenElement ||document.mozFullScreenElement ||document.msFullscreenElement ||document.oFullscreenElement;
            if (!flag) {
                //窗口大小设置
                document.querySelector('.show').style.height=600+'px';
                document.querySelector('.total_progress').style.width=650+'px';

                //切换图标
                document.querySelector('.pull_btn i').classList.remove('fa-compress');
                document.querySelector('.pull_btn i').classList.add('fa-arrows-alt');
            }
        }
    }



    //时间格式化 参数-秒
    function formatTime(time){
        if(typeof(time)!=="number"){
            return '00:00:00';
        }

        //获取hour
        var hour=parseInt(time/(60*60));
        hour = hour<10?'0'+hour:hour;

        //获取分钟
        var minute=parseInt(time%(60*60)/60);
        minute = minute<10?'0'+minute:minute;

        //获取秒钟
        var second=Math.ceil(time%60);
        second = second<10?'0'+second:second;

        return `${hour}:${minute}:${second}`;
    }
</script>
</body>
</html>

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,下面是一个简单的Vue原生兼容安卓和H5的短视频滑动播放器实现: 1. 首先需要安装 `vue-touch` 插件,它可以让我们方便地处理触摸事件。可以使用以下命令安装: ``` npm install vue-touch ``` 2. 在Vue组件中引入 `vue-touch` 插件: ```javascript import VueTouch from 'vue-touch'; Vue.use(VueTouch); ``` 3. 定义一个 `SwipePlayer` 组件,该组件包含一个视频播放器和一个滑动条: ```html <template> <div class="swipe-player"> <video :src="source" ref="videoRef"></video> <div ref="sliderRef" class="slider"></div> </div> </template> ``` 4. 在组件的 `mounted` 方法中,初始化滑动条,并添加滑动事件处理程序: ```javascript mounted() { // 初始化滑动条 const slider = this.$refs.sliderRef; slider.style.width = '0%'; // 添加滑动事件处理程序 this.$swipeRight(this.handleSwipeRight); this.$swipeLeft(this.handleSwipeLeft); }, methods: { // 处理向右滑动事件 handleSwipeRight() { const video = this.$refs.videoRef; const slider = this.$refs.sliderRef; // 获取当前视频播放进度 const currentTime = video.currentTime; const duration = video.duration; // 计算新的播放进度 const newTime = Math.max(currentTime - 5, 0); const percent = (newTime / duration) * 100; // 更新视频播放进度和滑动条 video.currentTime = newTime; slider.style.width = `${percent}%`; }, // 处理向左滑动事件 handleSwipeLeft() { const video = this.$refs.videoRef; const slider = this.$refs.sliderRef; // 获取当前视频播放进度 const currentTime = video.currentTime; const duration = video.duration; // 计算新的播放进度 const newTime = Math.min(currentTime + 5, duration); const percent = (newTime / duration) * 100; // 更新视频播放进度和滑动条 video.currentTime = newTime; slider.style.width = `${percent}%`; } } ``` 5. 在 `data` 中定义视频的源地址: ```javascript data() { return { source: 'http://example.com/video.mp4' }; } ``` 6. 最后,样式可以根据需要进行自定义: ```css .swipe-player { position: relative; width: 100%; height: 300px; } .swipe-player video { width: 100%; height: 100%; object-fit: cover; } .swipe-player .slider { position: absolute; bottom: 0; left: 0; width: 100%; height: 5px; background-color: #ddd; z-index: 1; } ``` 这样就完成了一个简单的Vue原生兼容安卓和H5的短视频滑动播放器
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值