zoukankan      html  css  js  c++  java
  • 自定义视频播放器(功能包括:播放/暂停,全屏,跳播)

    最终效果:

    1、demo结构

    fontawesome字体下载:http://fontawesome.dashgame.com/

    loading.gif:百度loading.gif选择一张下载

    2、index.html

      功能包括:播放/暂停,全屏,跳播

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>自定义视频播放器</title>
        <link rel="stylesheet" href="./css/font-awesome.min.css">
        <link rel="stylesheet" href="./css/index.css">                   
    </head>
    <body>
    <h3 class="player-title">视频播放器</h3>
    <div class="player-container">
        <video src="./mp4/test.mp4"></video>
        <div class="controls-container">
            <!-- 播放/暂停 -->
            <a href="javascript:;" class="switch fa fa-play"></a>
            <!-- 全屏 -->
            <a href="javascript:;" class="expand fa fa-expand"></a>
            <!-- 进度条 -->
            <div class="progress"><!-- 进度条底色 -->
                <div class="bar"></div><!-- 进度条最外层,用于事件控制 -->
                <div class="loaded"></div><!-- 已加载 -->
                <div class="current-progress"></div><!-- 已播放 -->
            </div>
            <!-- 当前播放时间, 视频总长 -->
            <div class="time">
                <span class="current-time">00:00:00</span>
                
                <span class="total-time">00:00:00</span>
            </div>
        </div>
    </div>
    
    <script type="text/javascript">
        // 播放器
        const video = document.querySelector('video');
        // "播放/暂停"切换按钮
        const switchBtn = document.querySelector('.switch');
        // 当前播放时间span
        const currentTimeSpan = document.querySelector('.current-time')
        // 视频总时长
        const totalTimeSpan = document.querySelector('.total-time')
        // 当前播放进度条
        const currentProgress = document.querySelector('.current-progress')
        // 获取进度条最外层,用于事件控制
        const bar = document.querySelector('.bar');
    
        // 实现"播放/暂停"
        switchBtn.onclick = function() {
            // 播放与暂停的切换
            if (video.paused) {
                video.play();
            } else {
                video.pause();
            }
            // 播放与暂停图标的切换
            this.classList.toggle('fa-pause');
            this.classList.toggle('fa-play');
        }
    
        // 实现"全屏"
        const playerContainer = document.querySelector('.player-container');
        document.querySelector('.expand').onclick = function() {
            if(playerContainer.requestFullScreen){
                playerContainer.requestFullScreen();
            } else if(playerContainer.webkitRequestFullScreen){
                playerContainer.webkitRequestFullScreen();
            } else if(playerContainer.mozRequestFullScreen){
                playerContainer.mozRequestFullScreen();
            } else if(playerContainer.msRequestFullScreen){
                playerContainer.msRequestFullScreen();
            }
        }
    
        // 当视频文件可以播放时触发
        // 当跳播时,修改了video.currentTime,也会触发该事件
        video.oncanplay = function() {
            console.log('触发oncanplay事件, video.currentTime=', video.currentTime)
            if (video.currentTime === 0) {
                setTimeout(function() {
                    console.log('视频缓存完成,可以播放了。。。')
                    // 显示视频第一帧画面
                    video.style.display = 'block'
                    // 获取当前视频文件总时长
                    const totalTime = video.duration;
                    console.log(`当前视频文件总时长: ${totalTime}秒`); // 单位为秒, 292.975736
                    // 页面显示视频总时长
                    totalTimeSpan.innerHTML = getTime(totalTime);
                }, 2000)
            }
    
        }
    
        // 当视频播放的时候会触发ontimeupdate事件,进度条同步,当前时间同步
        // 当跳播时,修改了video.currentTime,也会触发该事件
        video.ontimeupdate = function() {
            console.log('触发ontimeupdate事件。。。')
            // 获取当前时间
            const currentTime = video.currentTime;
            // 计算出视频的总时长
            const totalTime = video.duration;
            // 显示当前播放时间
            currentTimeSpan.innerHTML = getTime(currentTime);
            //进度条同步: 当前时间/总时间
            const value = currentTime / totalTime;
            currentProgress.style.width = value * 100 + "%";
            //当播放完毕之后,播放暂停按钮要转换成暂停按钮
            if (currentTime === totalTime) {
                switchBtn.classList.remove('fa-pause');
                switchBtn.classList.add('fa-pause');
            }
        }
    
        // 实现视频跳播
        bar.onclick = function(e) {
            // 获取鼠标点击位置相对bar最左侧的距离
            const offset = getOffsetX(e);
            // 获取bar的宽度
            const barWidth = this.style.width || this.clientWidth || this.offsetWidth || this.scrollWidth;
            console.log(`offset=${offset}, barWidth=${barWidth}`)
            const percent = offset / barWidth;
            const currentTime = percent * video.duration;
            video.currentTime = currentTime;
        }
    
        function getTime(time) {
            //转换时长
            let h = Math.floor(time / 3600);
            let m = Math.floor(time % 3600 / 60);
            let s = Math.floor(time % 60);
            //转换格式
            h = h > 10 ? h : "0" + h;
            m = m > 10 ? m : "0" + m;
            s = s > 10 ? s : "0" + s;
            return h + ":" + m + ":" + s;
        }
    
        // 火狐浏览器不支持e.offsetX,解决方法
        function getOffsetX(e){
            var e = e || window.event;
            var srcObj = e.target || e.srcElement;
            if (e.offsetX) {
                return e.offsetX;
            } else {
                var rect = srcObj.getBoundingClientRect();
                var clientx = e.clientX;
                return clientx - rect.left;
            }
        }
    </script>
    </body>
    </html>

    3、index.css

    body {
        padding: 0;
        margin: 0;
        font-family: 'microsofy yahei';
        background-color: #F7F7F7;
    }
    
    a {
        text-decoration: none;
    }
    
    .player-title {
        width: 100%;
        margin: 0 auto;
        line-height: 100px;
        font-size: 40px;
        text-align: center;
    }
    
    .player-container {
        width: 720px;
        height: 360px;
        margin: 0 auto;
        background: url('../images/loading.gif') center no-repeat;
        background-size: cover;
        position: relative;
    }
    video {
        height: 100%;
        margin: 0 auto;
        display: none;
    }
    
    /* ================ 播放器控制面板样式 start ================ */
    .controls-container {
        width: 720px;
        height: 40px;
        position: absolute;
        left: 0px;
        bottom: -40px;
        background-color: #000;
    }
    
    /* 播放/暂停 */
    .controls-container .switch {
        width: 20px;
        height: 20px;
        display: block;
        font-size: 20px;
        color: #fff;
        position: absolute;
        left: 10px;
        top: 10px;
    }
    /* 全屏 */
    .controls-container .expand {
        width: 20px;
        height: 20px;
        display: block;
        font-size: 20px;
        color: #fff;
        position: absolute;
        right: 10px;
        top: 10px;
    }
    /* 进度条 */
    .controls-container .progress {
        width: 430px;
        height: 10px;
        position: absolute;
        left: 40px;
        bottom: 15px;
        background-color: #555;
    }
    .controls-container .progress .bar {
        /* 100%;*/
        width: 430px;
        height: 100%;
        border-radius: 3px;
        cursor: pointer;
        position: absolute;
        left: 0;
        top: 0;
        opacity: 0;
        z-index: 999;
    }
    .controls-container .progress .loaded {
        width: 60%; /* 视频缓存的进度, 后期可动态变化 */
        height: 100%;
        background-color: #999;
        border-radius: 3px;
        position: absolute;
        left: 0;
        top: 0;
        z-index: 2;
    }
    .controls-container .progress .current-progress {
        width: 0%; /* 初始播放进度为0 */
        height: 100%;
        background-color: #fff;
        border-radius: 3px;
        position: absolute;
        left: 0;
        top: 0;
        z-index: 3;
    }
    .controls-container .time {
        height: 20px;
        position: absolute;
        left: 490px;
        top: 10px;
        color: #fff;
        font-size: 14px;
    }
    /* ================ 播放器控制面板样式 end ================ */

    4、测试

      1)打开index.html页面,视频加载完成打印"视频缓存完成,可以播放了。。。";

      2)点击进度条某个位置,首先触发了bar.onclick事件,计算并更新video.currentTime;然后触发了ontimeupdate事件和oncanplay事件。

      3)点击播放按钮;

      4)播放完毕后,发现一个小bug

      解决:

      删除代码:

    //当播放完毕之后,播放暂停按钮要转换成暂停按钮
    // if (currentTime === totalTime) {
    //     switchBtn.classList.remove('fa-pause');
    //     switchBtn.classList.add('fa-pause');
    // }

      添加代码:

    // 视频播放完毕,重置播放状态为初始状态
    video.onended = function() {
        video.currentTime = 0;
        switchBtn.classList.remove('fa-pause');
        switchBtn.classList.add('fa-pause');
    }

     ---

  • 相关阅读:
    H3BPM子表的复制
    vue规格新增一对多的例子
    vue自制switch滑块
    table垂直居中
    css清楚浮动的class
    网页之间的参数传递
    调用get_str_time(时间), 就能把毫秒的时间转换成格式化的 ,转化时间戳的方法
    css实现照片上传的加号框
    递归函数获得n个不重复的随机数
    随机生成n个不重复的数,范围是2-32,并让其在新页面打开
  • 原文地址:https://www.cnblogs.com/xy-ouyang/p/12349549.html
Copyright © 2011-2022 走看看