播放器自定义控制条

这是我目前做的,但并不完善,后期有时间还会修改过,但大致上已经可以了。

我写进度条样式的方法不是很好,我觉得把进度条最后的原点额外用一个div来控制比较好。我这里写的是用 :before 来控制的。

效果图:

播放器自定义控制条

引入的文件

<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/video-play.css">//自己写的
<script src="../jQuery版本/jquery-1.12.4.min.js"></script>
<script src="js/bootstrap.js"></script>
<script src="js/videoPlay.js"></script>//自己写的

主代码结构

<div id="player" class="player">
    <div id="videoBox" class="video-box text-center">
        <video id="film" width="100%" ondblclick="fullScreen()">
            <source src="video/遇见你之前Me.Before.You.2016.hd720p.x264.AAC.英语中文字幕.mp4" type="video/mp4"/>
        </video>
        
 		<!--屏幕中显示的这暂停/播放图标-->
        <img id="playImg" class="none" src="img/play.svg" alt="">
        <img id="pauseImg" class="none" src="img/pause.svg" alt="">

        <div id="controller" style="display: none;">
            <div class="custom-progress">
                <div class="progress-bar">
                    <div class="now"></div>
                </div>
            </div>
            <div class="controller-btns">
                <div class="controller-left">
                    <!--播放/暂停-->
                    <span class="glyphicon glyphicon-play pointer" onclick="playPause()"></span>
                    <span class="glyphicon glyphicon-pause pointer none" style="padding-right: 19px;"
                          onclick="playPause()"></span>
                    <!--停止-->
                    <span class="glyphicon glyphicon-stop pointer" onclick="stop()"></span>
                    <!--音量-->
                    <div class="sound-group">
                        <span class="glyphicon glyphicon-volume-up pointer" style="font-size: 19px;top:3px; padding-left:13px;"
                              onclick="soundMuted()"></span>
                            <span class="glyphicon glyphicon-volume-down pointer none" style="font-size: 19px;top:3px; padding-left:15px;"
                                  onclick="soundMuted()"></span>
                            <span class="glyphicon glyphicon-volume-off pointer none"
                                  style="font-size: 19px;padding-left: 11px;padding-right: 10px; top:3px;"
                                  onclick="soundMuted()"></span>
                            <div class="sound-progress" style="display: none;">
                                <div class="sound-now"></div>
                                <div class="show-sound-now none"></div>
                            </div>
                    </div>
                    <!--当前/总时间-->
                    <span class="start"></span>/<span class="end"></span>
                </div>
                <div class="controller-right">
                    <div class="rate-group">
                        <span class="rate">倍速</span>
                        <ul class="rate-dashboard none">
                                <li onclick="getRate(this)">2.0x</li>
                                <li onclick="getRate(this)">1.5x</li>
                                <li onclick="getRate(this)">1.25x</li>
                                <li style="color:#007ffe;" onclick="getRate(this)">1x</li>
                                <li onclick="getRate(this)">0.5x</li>
                        </ul>
                    </div>
                    <span class="glyphicon glyphicon-resize-full pointer" style="top:3px;"
                          onclick="fullScreen()"></span>
                    <span class="glyphicon glyphicon-resize-small pointer none" onclick="exitFullscreen()"></span>
                </div>
            </div>
        </div>
    </div>
</div>

css:

.none {
    display: none;
}

.player {
    position: relative;
    overflow: hidden;
    line-height: 1;
    height: 100%;
}

.video-box {
    width: 50%;
    height: auto;
    background-color: #000;
    position: relative;
}

video{
    width: 100%;
    position: relative;
}

.pointer {
    cursor: pointer;
    color: #ddd;
    font-size: 16px;
}

.pointer:hover {
    color: #fff;
}

/*自定义控制条*/
#controller {
    color: #eee;
    width: 100%;
    opacity: 1;
    -webkit-transform: translateY(100%);
    transform: translateY(100%);
    position: absolute;
    bottom: -5px;
    height: 41px;
    padding: 0 20px;
}

.controller-btns {
    position: relative;
    top: -40px;
    left: 0;
}

.controller-btns span {
    padding: 0 5px;
    width: 40px;
}

.controller-left {
    display: inline-block;
    position: absolute;
    top: 0;
    left: 0;
}

.controller-right {
    display: inline-block;
    position: absolute;
    top: 0;
    right: 0;
}

.custom-progress {
    width: 100%;
    position: relative;
    top: -50px;
    left: 0;
}

/*总进度条*/
.progress-bar {
    position: relative;
    width: 100%;
    height: 4px;
    background-color: #333333;
    vertical-align: 2px;
    border-radius: 4px;
    cursor: pointer;
}

.now {
    position: absolute;
    left: 2px;
    display: inline-block;
    height: 4px;
    background: #007ffe;
}

.now::after {
    content: '';
    position: absolute;
    top: -2px;
    left: 97%;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background-color: #007ffe;
}

.sound-group{
    display: inline-block;
}

/*音量进度条*/
.sound-progress {
    width: 60px;
    height: 5px;
    background-color: #fff;
    border-radius: 3px;
    cursor: pointer;
    display: inline-block;
    position: relative;
    top: -4px;
    left: -5px;
}

.sound-now {
    display: inline-block;
    width: 100%;
    border-radius: 3px;
    height: 5px;
    background: #007ffe;
    position: absolute;
    left: 0;
}

.sound-now::after {
    content: '';
    position: absolute;
    left: 95%;
    top: -2px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background-color: #007ffe;
}

.show-sound-now{
    display: inline-block;
    padding: 3px 5px;
    background-color: rgba(1,1,1,0.7);
    color: #eee;
    border-radius: 3px;
    position: absolute;
    top: -30px;
}

.rate-group{
    display: inline-block;
    width: 55px;
    border-radius: 14px;
    padding: 0 5px;
}

.rate{
    display: inline-block;
    height: 22px;
    text-align: center;
    line-height: 22px;
    color: #fff;
    cursor: pointer;
}

.rate-group:hover{
    background-color: #007ffe;
}

.rate-dashboard{
    list-style: none;
    position: absolute;
    top: -170px;
    left: -40px;
}


.rate-dashboard >li{
    display: block;
    cursor: pointer;
    background-color: rgba(0, 0, 0, 0.8);
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: 0 0 16px 0 rgba(0, 0, 0, 0.2);
    border-radius: 1px;
    color: #fff;
    text-align: center;
    line-height: 30px;
    font-size: 12px;
    padding: 0 15px;
}
.rate-dashboard >li:hover{
    background-color: rgba(0,0,0,0.5);
}

/*屏幕中播放/暂停图标*/
#videoBox img{
    padding: 15px;
    border-radius: 50%;
    background-color: rgba(255,255,255,0.2);
    position: absolute;
    top: 40%;
    right: 42.5%;
    width: 100px;
    cursor: pointer;
}

js:

var videoBox = document.getElementById("videoBox");
var myVideo = document.getElementById("film");
var soundNow = document.getElementsByClassName("sound-now")[0];
var playImg = document.getElementById("playImg");
var pauseImg = document.getElementById("pauseImg");

var last="100%",timeId;


/*停止-跳回开头*/
function stop() {
    myVideo.pause();
    myVideo.currentTime = 0;
}

/*全屏*/
function fullScreen() {
    if (videoBox.requestFullscreen) {
        videoBox.requestFullscreen();
        myVideo.style.width = "100%";
        myVideo.style.height = "auto";
    } else if (videoBox.mozRequestFullScreen) {
        videoBox.mozRequestFullScreen();
        myVideo.style.width = "100%";
        myVideo.style.height = "auto";
    } else if (videoBox.webkitRequestFullScreen) {
        videoBox.webkitRequestFullScreen();
        myVideo.style.width = "100%";
        myVideo.style.height = "auto";
    }
    $(".glyphicon-resize-full").hide();
    $(".glyphicon-resize-small").show();
}

/*退出全屏*/
function exitFullscreen() {
    var de = document;
    if (de.exitFullscreen) {
        de.exitFullscreen();
        myVideo.style.width = "100%";
        myVideo.style.height = "auto";
    } else if (de.mozCancelFullScreen) {
        de.mozCancelFullScreen();
        myVideo.style.width = "100%";
        myVideo.style.height = "auto";
    } else if (de.webkitCancelFullScreen) {
        de.webkitCancelFullScreen();
        myVideo.style.width = "100%";
        myVideo.style.height = "auto";
    }
}

/*音量*/
function soundMuted() {
    if (myVideo.muted) {//未静音
        myVideo.muted = false;
    } else {//静音
        myVideo.muted = true;
        soundNow.style.width = "0";
    }
}

/*倍速播放*/
function getRate(element){
    console.log();
    myVideo.playbackRate = parseFloat(element.innerHTML);
}


/*播放/暂停*/
function playPause() {
    if (myVideo.paused){
        myVideo.play();
        pauseImg.style.display="none";
        playImg.style.display="block";
        $("#playImg").fadeIn(400);
        timeId=setInterval("hideScreenPlay()",300)
    }else{
        myVideo.pause();
        pauseImg.style.display="block";
    }
}
function hideScreenPlay(){
    $("#playImg").fadeOut(300);
    clearInterval(timeId);
}



/******************* jQuery ***********************/
$(function () {
    var play = $(".glyphicon-play");
    var pause = $(".glyphicon-pause");
    var full = $(".glyphicon-resize-full");
    var exitFull = $(".glyphicon-resize-small");
    var soundUp = $(".glyphicon-volume-up");
    var soundDown = $(".glyphicon-volume-down");
    var muted = $(".glyphicon-volume-off");
    var soundProgress=$(".sound-progress");



    $(".video-box").mousemove(function () {
        $("#controller").fadeIn(400);
    }).mouseleave(function () {
        $("#controller").fadeOut(400);
    });


    /*点击视频暂停/播放*/
    /*此处右问题,点击视频处仅一次有效*/
    // $("#film,#pauseImg,#playImg").click(function () {
    //     if(pause.show()){ //播放状态
    //         $("#pauseImg").fadeIn(500);
    //         playPause();
    //         pause.hide();
    //         play.show();
    //     }else{ //暂停状态
    //         pause.show();
    //         play.hide();
    //     }
    // });


    /*切换显示图标*/
    play.click(function () {//播放状态
        $(this).hide();
        pause.show();
        // flag=true;
    });
    pause.click(function () {//暂停状态
        $(this).hide();
        play.show();
        // flag=false;
    });

    full.click(function () {
        $(this).hide();
        exitFull.show();
    });
    exitFull.click(function () {
        $(this).hide();
        full.show();
    });

    soundUp.click(function () {
        $(this).hide();
        muted.show();
    });
    soundDown.click(function () {
        $(this).hide();
        muted.show();
    });
    muted.click(function () {
        $(this).hide();
        soundNow.style.width = last;
        last === "100%" ? soundUp.show() : soundDown.show();
    });



    /*显示音乐进度条*/
    $(".sound-group").mouseover(function () {
        soundProgress.stop().show(400);
    }).mouseout(function () {
        soundProgress.stop().hide(400);

    });

    /*点击音量进度条*/
    soundProgress.click(function (event) {
        muted.hide();
        last === "100%" ? soundUp.show() : soundDown.show();
        myVideo.muted = false;
        let soundWidth = event.pageX - this.getBoundingClientRect().left;
        soundWidth = soundWidth < 0 ? 0 : soundWidth;
        soundWidth = soundWidth > this.offsetWidth ? this.offsetWidth : soundWidth;
        let p = soundWidth / this.offsetWidth;
        soundNow.style.width = p.toFixed(2) * 100 + '%';
        last = p.toFixed(2) * 100 + '%';
        myVideo.volume = p;

        $(".show-sound-now").stop().show().text(soundNow.style.width).delay(1000).hide(0);

        if (soundNow.style.width === "0%") {
            soundUp.hide();
            soundDown.hide();
            muted.show();
        } else if (soundNow.style.width === "100%") {
            muted.hide();
            soundDown.hide();
            soundUp.show();
        } else {
            soundUp.hide();
            muted.hide();
            soundDown.show();
        }
    });

    /*点击倍速*/
    $(".rate").click(function () {
        $(".rate-dashboard").show().children("li").click(function(){
            $(this).css("color","#007ffe").siblings().css("color","#eee");
            var t=$(this).text();
            $(".rate").text(t);
            $(this).parent().hide();
        });
    });

});


/******* 视频进度条 ********/
    // const 定义的变量不可以修改,而且必须初始化
const video = document.getElementById('film');
const start = document.querySelector('.start');
const end = document.querySelector('.end');
const progressBar = document.querySelector('.progress-bar');
const now = document.querySelector('.now');

// let 声明的变量只在该花括号内有效(块级作用域),要声明才可用
function conversion(value) {
    let minute = Math.floor(value / 60);
    minute = minute.toString().length === 1 ? ('0' + minute) : minute;
    let second = Math.round(value % 60);
    second = second.toString().length === 1 ? ('0' + second) : second;
    return `${minute}:${second}`
}

video.onloadedmetadata = function () {
    end.innerHTML = conversion(video.duration);
    start.innerHTML = conversion(video.currentTime);
};

progressBar.addEventListener('click', function (event) {
    //getBoundingClientRect();
    // 这个方法返回一个矩形对象,包含四个属性:left、top、right和bottom。分别表示元素各边与页面上边和左边的距离。
    let coordStart = this.getBoundingClientRect().left;
    let coordEnd = event.pageX;
    let p = (coordEnd - coordStart) / this.offsetWidth;
    now.style.width = p.toFixed(3) * 100 + '%';

    video.currentTime = p * video.duration;
    video.play()
});

setInterval(() => {
    start.innerHTML = conversion(video.currentTime);
    now.style.width = video.currentTime / video.duration.toFixed(3) * 100 + '%'
}, 1000)