自定義視訊播放器

吞石魚發表於2018-08-30

完整程式碼,視訊為網路資源

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            * {
                margin: 0;
                padding: 0;
            }

            html,
            body {
                height: 100%;
                width: 100%;
                overflow: hidden;
            }

            #videoWrap {
                height: 100%;
                width: 100%;
                background-color: #383838;
            }

            #myVideo {
                display: block;
            }

            #footer {
                width: 100%;
                height: 25px;
                background-color: #2A2A2A;
                position: relative;
            }
            /*按鈕組*/

            #footer .btns {
                width: 55px;
                height: 25px;
                display: flex;
                justify-content: space-around;
                align-items: center;
                position: absolute;
                left: 0;
                top: 0;
            }

            #footer .btns .start,
            #footer .btns .end {
                width: 9px;
                height: 11px;
                background: url(icon.png) no-repeat;
            }

            #footer .btns .start {
                background-position: 0 -22px;
            }

            #footer .btns .start.active {
                background-position: 0 -10px;
            }

            #footer .btns .end {
                background-position: 0 1px;
            }
            /*其他*/

            #footer .others {
                width: 230px;
                height: 25px;
                position: absolute;
                right: 0;
                top: 0;
            }

            #footer .others>div {
                float: left;
            }

            #footer .others .time {
                width: 120px;
                font-size: 12px;
                color: white;
                text-align: center;
                line-height: 25px;
            }

            #footer .others .volume {
                width: 80px;
                height: 25px;
            }

            #footer .others .volume .isSonud {
                width: 20px;
                height: 25px;
                position: relative;
                float: left;
            }

            #footer .others .volume .isSonud>span {
                position: absolute;
                top: 0;
                left: 0;
                bottom: 0;
                right: 0;
                margin: auto;
                width: 12px;
                height: 12px;
                background: url(icon.png) no-repeat;
                background-position: 0 -34px;
            }

            #footer .others .volume .isSonud>span.active {
                background-position: 0 -46px;
            }

            #footer .others .volume .progress {
                width: 60px;
                height: 25px;
                float: left;
                margin: 0;
            }

            #footer .others .volume .progress .smallWhite {
                width: 9px;
                height: 7px;
                background-color: white;
                border-radius: 2px;
                position: absolute;
                top: -2px;
                left: 0;
            }

            #footer .others .volume .progress .smallPink {
                height: 3px;
                width: 0px;
                position: absolute;
                top: 0;
                bottom: 0;
                margin-top: auto;
                margin-bottom: auto;
                background-color: deeppink;
            }

            #footer .others .volume .progress .smallGrey {
                height: 3px;
                width: 100%;
                position: absolute;
                top: 0;
                bottom: 0;
                margin-top: auto;
                margin-bottom: auto;
                background-color: #737373;
            }

            #footer .progress {
                height: 25px;
                margin: 0 230px 0 55px;
                position: relative;
            }

            #footer .progress .smallGrey {
                height: 3px;
                width: 100%;
                position: absolute;
                top: 0;
                bottom: 0;
                margin-top: auto;
                margin-bottom: auto;
                background-color: #737373;
            }

            #footer .progress .smallWhite {
                width: 9px;
                height: 7px;
                background-color: white;
                border-radius: 2px;
                position: absolute;
                top: -2px;
                left: 0;
            }

            #footer .progress .smallPink {
                height: 3px;
                width: 0px;
                position: absolute;
                top: 0;
                bottom: 0;
                margin-top: auto;
                margin-bottom: auto;
                background-color: deeppink;
            }

            #footer .full {
                width: 30px;
                height: 25px;
                text-align: center;
                line-height: 25px;
            }

            #footer .full>span {
                display: inline-block;
                margin: 7px auto;
                width: 11px;
                height: 11px;
                background: url(icon.png) no-repeat;
                background-position: 0 -58px;
            }

            #footer .full>span.active {
                background-position: 0 -70px;
            }
        </style>
    </head>

    <body>
        <section id="videoWrap">
            <!--視訊模組-->
            <video src="http://img.ksbbs.com/asset/Mon_1703/eb048d7839442d0.mp4" id="myVideo" id="myVideo"></video>
            <!--底部功能模組-->
            <div id="footer">
                <!--按鍵組-->
                <div class="btns">
                    <!--開始    暫停通過對span新增active類從而更改雪碧圖-->
                    <div class="start"></div>
                    <!--結束按鈕-->
                    <div class="end"></div>
                </div>
                <!--進度條-->
                <div class="progress">
                    <!--小灰  未播放進度-->
                    <div class="smallGrey">
                        <!--小白塊 -->
                        <div class="smallWhite"></div>
                    </div>
                    <!--小粉 已播放進度-->
                    <div class="smallPink"></div>
                </div>
                <!--右側  時間,聲音外掛,全屏外掛-->
                <div class="others">
                    <div class="time">
                        <span>00:00:00</span>/
                        <span>00:00:00</span>
                    </div>
                    <!--聲音外掛-->
                    <div class="volume">
                        <!--是否靜音-->
                        <div class="isSonud">
                            <span></span>
                        </div>
                        <!--聲音條-->
                        <div class="progress">
                            <div class="smallGrey">
                                <div class="smallWhite"></div>
                            </div>
                            <div class="smallPink"></div>
                        </div>
                    </div>
                    <div class="full">
                        <span></span>
                    </div>
                </div>
            </div>
        </section>
    </body>
    <script src="js/drag.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript">
        window.onload = function() {
            var myVideo = document.querySelector('#myVideo');
            var footer = document.getElementById('footer');
            var start = document.querySelector('#footer .btns .start');
            var end = document.querySelector('#footer .btns .end');
            var isSound = document.querySelector('#footer .others .volume .isSonud>span');
            var time = document.querySelectorAll('#footer .others .time span');
            var full = document.querySelector('#footer .full>span');
            var timer = null;
            var isFullScreen = false;

            var progress = document.querySelectorAll('#footer .progress');
            var smallGrey = document.querySelectorAll('#footer .progress .smallGrey');
            var smallWhite = document.querySelectorAll('#footer .progress .smallGrey .smallWhite')
            var smallPink = document.querySelectorAll('#footer .progress .smallPink');
            var volume = 1;
            myVideo.width = document.documentElement.clientWidth;
            myVideo.height = document.documentElement.clientHeight - footer.offsetHeight;

             //當遊覽器大小改變,視訊自適應
            window.onresize = function() {
                myVideo.width = document.documentElement.clientWidth;
                myVideo.height = document.documentElement.clientHeight - footer.offsetHeight;
            }
            //拖動邏輯    通過小粉left可知當前時間
            //總時間
            myVideo.onloadedmetadata = function() {
                time[1].innerHTML = changeTime(myVideo.duration);
            };

            //音量樣式初始化   小白塊和粉色條 達到最大化樣式
                smallPink[1].style.width = smallGrey[1].offsetWidth - smallWhite[1].offsetWidth + 'px';
                smallWhite[1].style.left = (smallGrey[1].offsetWidth - smallWhite[1].offsetWidth) + 'px';


            //所有操作邏輯封裝
            function dragWhite() {
                //點選開始按鈕    
                start.onclick = function() {
                    if(myVideo.paused) {
                        myVideo.play();
                        addClass(start, 'active');
                        timer = setInterval(move, 50);

                    } else {
                        myVideo.pause()
                        removeClass(start, 'active')
                        clearInterval(timer);
                    }
                } 
                //點選結束按鈕     樣式  暫停  停止小白塊   更新視訊當前時間
                end.onclick = function() {
                    removeClass(start, 'active');
                    smallPink[0].style.width = smallWhite[0].style.left = 0+'px';
                    myVideo.pause();
                    clearInterval(timer);                   
                    myVideo.currentTime = 0
                }

                //進度條點選
                progress[0].onclick = function(e) {
                    addClass(start, 'active');
                    //小白塊和粉色條跟隨
                    smallPink[0].style.width = smallWhite[0].style.left = e.clientX - progress[0].offsetLeft + 'px';
                    //視訊當前時間更新
                    myVideo.currentTime = smallWhite[0].offsetLeft / (smallGrey[0].offsetWidth - smallWhite[0].offsetWidth) * myVideo.duration;
                    //播放並讓小白塊走起
                    myVideo.play();
                    timer = setInterval(move, 50);
                }

                //音量條點選
                progress[1].onclick=function(e){
                    //小白塊和粉色條跟隨
                    smallPink[1].style.width = smallWhite[1].style.left = e.clientX - progress[1].offsetLeft-progress[0].offsetWidth-progress[0].offsetLeft + 'px';
                    myVideo.volume = smallWhite[1].offsetLeft / (smallGrey[1].offsetWidth - smallWhite[1].offsetWidth);
                    volume = myVideo.volume;
                    //當音量=0時觸發靜音事件
                        if(myVideo.volume == 0) {
                            myVideo.muted = true;
                            addClass(isSound, 'active');
                        } else {
                            myVideo.muted = false;
                            removeClass(isSound, 'active');
                        }
                }


                //拖動邏輯    此處我們對進度條小白塊進行拖動,並通過callback1物件內的move函式完成對當前時間的更新
                var callback1 = {
                    move: function() {
                        //小粉條跟隨
                        smallPink[0].style.width=smallWhite.offsetLeft+'px';
                        //計算當前時間並更新
                        myVideo.currentTime = smallWhite[0].offsetLeft / (smallGrey[0].offsetWidth - smallWhite[0].offsetWidth) * myVideo.duration;
                        time[0].innerHTML = changeTime(myVideo.currentTime);
                    }
                }


               //拖動邏輯    此處我們對音量小白塊進行拖動,並通過callback2物件內的move函式完成對當前時間的更新
                var callback2 = {
                    move: function() {
                        smallPink[1].style.width = smallWhite[1].offsetLeft + 'px';
                        myVideo.volume = smallWhite[1].offsetLeft / (smallGrey[1].offsetWidth - smallWhite[1].offsetWidth);
                        //儲存聲音變數到全域性環境
                        volume = myVideo.volume;
                        //當音量=0時觸發靜音事件
                        if(myVideo.volume == 0) {
                            myVideo.muted = true;
                            addClass(isSound, 'active');
                        } else {
                            myVideo.muted = false;
                            removeClass(isSound, 'active');
                        }
                    }
                }               
                $.drag(smallWhite[0], callback1);          
                $.drag(smallWhite[1], callback2);



                //是否靜音按鈕
                isSound.onclick = function() {
                    //開始時不靜音  myVideo.muted=false  ==>true  執行靜音語句  小白小粉歸零
                    if(!myVideo.muted) {
                        myVideo.muted = true;
                        addClass(isSound, 'active');
                        smallWhite[1].style.left = smallPink[1].style.width = 0 + 'px';
                    } else {
                        myVideo.muted = false;
                        removeClass(isSound, 'active');
                        //拿到全域性聲音變數,使靜音取消具有記錄功能
                        smallWhite[1].style.left = smallPink[1].style.width = volume * (smallGrey[1].offsetWidth - smallWhite[1].offsetWidth) + 'px';
                    }

                }
            }
            dragWhite();

            //全屏邏輯
            full.onclick = function() {
                if(isFullScreen) {
                    removeClass(full, 'active')
                    isFullScreen = false
                    if(document.exitFullscreen) {
                        document.exitFullscreen();
                    } else if(document.mozCancelFullScreen) {
                        document.mozCancelFullScreen();
                    } else if(document.webkitCancelFullScreen) {
                        document.webkitCancelFullScreen();
                    } else if(document.msExitFullscreen) {
                        document.msExitFullscreen();
                    }
                } else {
                    addClass(full, 'active')
                    isFullScreen = true
                    var docElm = document.documentElement;
                    //W3C  
                    if(docElm.requestFullscreen) {
                        docElm.requestFullscreen();
                    }
                    //FireFox  
                    else if(docElm.mozRequestFullScreen) {
                        docElm.mozRequestFullScreen();
                    }
                    //Chrome等  
                    else if(docElm.webkitRequestFullScreen) {
                        docElm.webkitRequestFullScreen();
                    }
                    //IE11
                    else if(docElm.msRequestFullscreen) {
                        docElm.msRequestFullscreen();
                    }
                }
            }

            //進度條移動
            function move() {
                smallWhite[0].style.left = smallPink[0].style.width = myVideo.currentTime / myVideo.duration * (smallGrey[0].offsetWidth - smallWhite[0].offsetWidth) + 'px';
                time[0].innerHTML = changeTime(myVideo.currentTime);
            }

            //公共函式
            //時間格式
            function changeTime(time) {
                time = parseInt(time);

                var h = toZero(Math.floor(time / 3600));
                var m = toZero(Math.floor(time % 3600 / 60));
                var s = toZero(Math.floor(time % 60));;

                return h + ":" + m + ":" + s;
            }

            function toZero(mun) {
                if(mun < 10) {
                    mun = "0" + mun;
                } else {
                    mun = "" + mun;
                }
                return mun;
            }

            //class操作函式
            function addClass(node, className) {
                var reg = new RegExp("\\b" + className + "\\b");
                if(!reg.test(node.className)) {
                    node.className += (" " + className);
                }
            }

            function removeClass(node, className) {
                if(node.className) {
                    var reg = new RegExp("\\b" + className + "\\b");
                    var classes = node.className;
                    node.className = classes.replace(reg, "");
                    if(/^\s*$/g.test(node.className)) {
                        node.removeAttribute("class");
                    }
                } else {
                    node.removeAttribute("class");
                }
            }
        }
    </script>

</html>

相關文章