video自定義播放器

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

> 此自定義播放器基於JS ,內部只用了少量JQ 此播放器可以拖動進度條, 也可以點擊進度條的任一位置進行播放,同理聲音也是如此, 有全屏功能,以及調節播放速度。

用法超級簡單
在這裏插入圖片描述
當然如果要修改樣式以及其他需求, 核心代碼都是不需要改變的

html:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>video</title>
    <link rel="stylesheet" href="video.css">
</head>

<body>
    <div  id="details-video"> </div>
    <script src="jquery-1.11.1.min.js"></script>
    <script src="video.js"></script>
    <script>
        comm_medias('details-video', { src: '' });
    </script>
</body>

</html>
css
.media-controller {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 50px;
  box-sizing: border-box;
  background: rgba(0, 0, 0, 0.3);
}
.media-progress {
  position: absolute;
  top: 0;
  height: 8px;
  width: 100%;
  background: rgba(0, 0, 0, 0.6);
  box-sizing: border-box;
  cursor: pointer;
}
.media-bar {
  position: absolute;
  top: 0px;
  height: 8px;
  width: 0;
  background: #aaa;
}
.media-circular {
  width: 12px;
  height: 12px;
  border-radius: 100%;
  background: #fff;
  position: absolute;
  top: -2px;
  left: -6px;
}
.media-center {
  position: absolute;
  width: 100%;
  box-sizing: border-box;
  bottom: 12px;
  line-height: 20px;
}
.media-play-stop {
  float: left;
  margin-left: 20px;
  cursor: pointer;
  width: 15px;
  height: 20px;
  overflow: hidden;
}
.media-play {
  height: 0;
  width: 0;

  display: inline-block;
  border: 12px solid #fff;
  border-color: transparent transparent transparent #fff;
  border-right-width: 0;
  border-top-width: 10px;
  border-bottom-width: 10px;
}
.media-stop {
  height: 20px;
  width: 4px;
  background: #fff;
  float: left;
  position: relative;
}
.media-stop::after {
  content: " ";
  position: absolute;
  height: 20px;
  width: 4px;
  left: 10px;
  background: #fff;
}
.media-time {
  display: inline-block;
  color: #fff;
  margin-left: 26px;
  float: left;
}
.media-volume-control {
  cursor: pointer;
  float: right;
  margin-right: 20px;
  border-radius: 50px;
  height: 20px;
  width: 100px;
  background: rgba(0, 0, 0, 0.6);
}
.media-volume-progress {
  float: right;
  height: 5px;
  width: 80px;
  background: #aaa;
  border-radius: 50px;
  margin-right: 10px;
  margin-top: 7.5px;
}
.media-volume-horizontal {
  height: 5px;
  width: 0;
  background: #fff;
  border-radius: 50px;
}
.media-full {
  cursor: pointer;
  float: right;
  border: 1px solid #fff;
  width: 20px;
  height: 20px;
  display: inline-block;
  box-sizing: border-box;
  margin-right: 30px;
}
.media-ico {
  position: absolute;
  z-index: 10;
  width: 60px;
  height: 60px;
  background: rgba(0, 0, 0, 0.4);
  border-radius: 100%;
  top: 50%;
  left: 50%;
  margin-left: -30px;
  margin-top: -30px;
  cursor: pointer;
}
.media-ico::after {
  content: " ";
  width: 0;
  height: 0;
  display: inline-block;
  border: 15px solid #fff;
  border-color: transparent transparent transparent #fff;
  border-right-width: 0;
  border-top-width: 12px;
  border-bottom-width: 12px;
  margin-left: 26.25px;
  margin-top: 18px;
}
.media-ico:hover {
  background: rgba(0, 0, 0, 0.6);
  box-shadow: 0 0 6px #f3f3f3;
}
.media-speed {
  float: right;
  color: #fff;
  margin-right: 15px;
  cursor: pointer;
  position: relative;
}
.media-speed-item {
  display: none;
  position: absolute;
  top: -50px;
  border-radius: 6px;
  background: rgba(0, 0, 0, 0.5);
  width: 200px;
  left: -80px;
  overflow: hidden;
  height: 30px;
  padding: 0;
}
.media-speed .media-speed-item li {
  float: left;
  margin-right: 0 !important;
  cursor: pointer;
  width: 30px !important;
  line-height: 30px;
  padding: 0px 5px;
  box-sizing: content-box;
  text-align: center;
  list-style: none;
  font-size: 12px;
}
.media-speed .media-speed-item li.active {
  background: rgba(0, 0, 0, 0.7);
  border-radius: 6px;
}

js

function comm_medias(id, data) {
    if (data.src.length > 0) {
        var panlParent = $("#" + id);//傳入一個div 的ID
        var videoNode = document.createElement("VIDEO");//new 一個VOID的實例

        ~function orgHtml() {
            //  這個是正確的配置方式
            // videoNode.style.objectFit = "fill";
            // videoNode.style.width = '100%';
            // videoNode.style.height = '100%';
            // panlParent.css("width", 500);
            // panlParent.css("height", 500);

            videoNode.style.objectFit = "fill";
            videoNode.style.width = '100%';
            videoNode.style.height = '100%';
            panlParent.css("width", 600);
            panlParent.css("height", 310);

            videoNode.setAttribute("src", data.src);
            panlParent.css("position", "relative");
            panlParent.css("overflow", "hidden");
            panlParent.addClass("clear");
            var setOption = '';
            setOption += '<div class="media-ico"></div>';
            setOption += '<div class="media-controller">';
            setOption += '    <div class="media-progress">';
            setOption += '        <div class="media-bar"></div>';
            setOption += '        <div class="media-circular"></div>';
            setOption += '    </div>';
            setOption += '    <div class="media-center clear">';
            setOption += '       <div class="media-play-stop">';
            setOption += '          <span class="media-play"></span>';
            setOption += '        </div>';
            setOption += '        <div class="media-time">';
            setOption += '             <span class="media-current">00 : 00 : 00</span><font style="margin: 0 3px;">/</font><span class="media-total" >00 : 00 : 00</span>';
            setOption += '        </div>';
            setOption += '        <div class="media-full"></div>';
            if (panlParent.width() >= 415) {
                setOption += '        <div class="media-volume-control">';
                setOption += '          <div class="media-volume-progress">';
                setOption += '              <div class="media-volume-horizontal"></div>';
                setOption += '            </div>';
                setOption += '        </div>';
                setOption += '        <div class="media-speed clear">倍速';
                setOption += '              <ul class="media-speed-item clear">';
                setOption += '                  <li>0.5x</li>';
                setOption += '                  <li>1.0x</li>';
                setOption += '                  <li>1.25x</li>';
                setOption += '                  <li>1.5x</li>';
                setOption += '                  <li>2.0x</li>';
                setOption += '              </ul>';
                setOption += '        </div>';
            }
            setOption += '    </div>';
            setOption += '</div>';

            panlParent.append(videoNode);
            panlParent.append(setOption);
        }()

        var media_current, media_total, media_bar, media_play_stop, media_progress, media_volume_progress,
            media_full, media_ico, media_controller, media_speed_item, media_speed, media_circular;
        ~function DocElements() {
            media_current = panlParent.find(".media-current");//看過的時間
            media_total = panlParent.find(".media-total");//總時長
            media_bar = panlParent.find(".media-bar")//正在播放的進度條
            media_play_stop = panlParent.find(".media-play-stop")//播放暫停按鈕
            media_progress = panlParent.find(".media-progress")//播放的進度條總長
            media_volume_progress = panlParent.find(".media-volume-progress")//固定的音量
            media_volume_horizontal = panlParent.find(".media-volume-horizontal")//拖動的條音量
            media_full = panlParent.find(".media-full");//全屏
            media_ico = panlParent.find(".media-ico")//屏幕中間的播放
            media_controller = panlParent.find(".media-controller")//顯示隱藏
            media_speed_item = panlParent.find(".media-speed-item")//控制播放速率
            media_speed = panlParent.find(".media-speed");//顯示播放速率
            media_circular = panlParent.find(".media-circular")//拖動球
        }()

        ~function EventTag() {
            /**
            * 當前可播放狀態
            */
            videoNode.addEventListener('canplay', function () {//低版本不識別 videoNode.oncanplay
                try {
                    var type = videoNode.error;
                    panlParent.hide();
                    if (type == null) {
                        //顯示視頻
                        panlParent.show();
                    } else if (type.code == 1) {
                        //隱藏視頻頻
                        console.log("用戶終止視頻文件加載");
                    } else if (type.code == 2) {
                        console.log("視頻文件網絡錯誤");
                    } else if (type.code == 3) {
                        console.log("視頻文件解碼錯誤");
                    } else if (type.code == 4) {
                        console.log("視頻文件URL無效");
                    }

                    //顯示視頻總時長
                    media_total.html(getFormatTime(videoNode.duration))
                    videoNode.volume = 0.5;
                    media_volume_horizontal.width(media_volume_progress.width() / 2);
                    videoNode.controls = false;
                } catch (ex) {
                    console.log(ex);
                }
            });

            /**
             * 播放停止
             */
            function plays() {
                if (videoNode) {
                    if (videoNode.paused) {
                        videoNode.play();
                        media_play_stop.find("span")[0].className = "media-stop";
                        media_ico.hide();
                    } else {
                        videoNode.pause();
                        media_play_stop.find("span")[0].className = "media-play";
                        media_ico.show();
                    }
                    return false;
                } else {
                    alert("瀏覽器不支持video標籤,或者資源沒有正確加載");
                }
            }
            /**
            * 給播放按鈕賦上點擊事件
            */
            media_play_stop.off('click').click(plays);
            media_ico.off('click').click(plays);
            /**
             * 進度條
             * videoNode.ontimeupdate = function (){}在Chrome上無效,可以使用addEventListener來代替它: 
             */
            videoNode.addEventListener('timeupdate', function () {
                setTimeout(function () {
                    var type = videoNode.networkState;
                    if (type == 0 || type == 3) {
                        panlParent.hide(); //網絡問題就隱藏掉
                    } else {
                        panlParent.show();
                    }
                }, 10);
                //要實現的功能,首先是進度條根據視頻播放的進度,不斷的增加。意思就是不斷的獲取視頻的當前進度,然後去除以視頻的總長度,拿這個比值乘以進度條的總長度,就得到經度條當前的長度,賦值
                var currTime = this.currentTime,    //當前播放時間
                    duration = this.duration;       // 視頻總時長
                //百分比
                // var scales = currTime / duration * 100 + "%"; //百分比的獲取方式
                var scales = currTime / duration * panlParent.width();
                //顯示進度條
                media_bar.css("width", scales);
                //顯示進度球
                media_circular.css("left", scales - 6);
                //顯示當前播放進度時間
                media_current.html(getFormatTime(currTime));
            })

            /**
             * 跳躍播放
             */
            media_progress.off('click').click(function (e) {
                var event = e || window.event;
                var w = this.offsetWidth;//本身的寬度
                var v = event.offsetX;//點擊的距離
                if (v < 0) {
                    v = 0;
                } else if (v > w) {
                    v = w;
                }
                var scale = v / w;
                //得到所點擊的距離佔比, 乘以總長時間,0.8*time
                videoNode.currentTime = scale * videoNode.duration;
                return false;
            });

            /**
             * 進度條控制拖拽
             * 拖動經度條,視頻在相應的位置播放。反過來,先獲取進度條的當前位置,除以進度條的總長度,拿這個比值乘以視頻的總長度,就得到視頻當前應該播放的進度,賦值。
             */
            var moveFlag = false;
            media_circular.off('mousedown').mousedown(function (e) {
                // console.log('left :', media_circular.offset().left);//不能用這個 相對於文檔窗口  

                moveFlag = true;
                var event = e || window.event;
                var x = event.clientX;
                console.log('offsetLeft :');//相對與父元素
                var nowLocation = media_circular[0].offsetLeft; //進度條的當前位置
                var width = media_progress.width(); //進度條的總長度
                // videoNode.currentTime = nowLocation / width * videoNode.duration;  //視頻當前進度 =  進度條的當前位置 /進度條的總長度 * 視頻的總長度 

                document.onmousemove = function (e) {
                    if (moveFlag) {
                        var event = e || window.event;
                        var moveX = event.clientX - x; //移動後的距離 - 去移動前的距離
                        var allLeft = moveX + nowLocation; //等於總共的偏移量(正負都包含了)
                        if (allLeft < 0) {
                            allLeft = 0;
                        }
                        if (allLeft > width) {
                            allLeft = width;
                        }
                        media_circular.css("left", allLeft);//球移動了這麼多的距離
                        media_bar.css("width", allLeft);
                        //視頻當前進度 =  進度條的當前位置 /進度條的總長度 * 視頻的總長度 
                        videoNode.currentTime = allLeft / width * videoNode.duration;

                    }
                }
                document.onmouseup = function () {
                    document.onmousedown = null;
                    document.onmousemove = null;
                    moveFlag = false;
                }
            })


            /**
             * 跳躍音量條
             */
            media_volume_progress.off('click').click(function (e) {
                var event = e || window.event;
                var w = this.offsetWidth;//本身的寬度
                var v = event.offsetX;//點擊的距離
                if (v < 0) {
                    v = 0;
                } else if (v > w) {
                    v = w;
                }
                var scale = v / w;
                //得到所點擊的距離佔比, 乘以總音量,0.8*volume
                videoNode.volume = scale;
                media_volume_horizontal.width(v);
                return false;
            });



            /**
            * 進入全屏
            */
            function requestFullScreen() {
                if (videoNode.requestFullscreen) {
                    videoNode.requestFullscreen();
                } else if (videoNode.mozRequestFullScreen) {
                    videoNode.mozRequestFullScreen();
                } else if (videoNode.webkitRequestFullScreen) {
                    videoNode.webkitRequestFullScreen();
                } else if (videoNode.msRequestFullscreen) {
                    videoNode.msRequestFullscreen()
                }
            }

            media_full[0].addEventListener("click", requestFullScreen, false);

            /**
             * 退出全屏
             */
            function cancelFullScrren(elem) {
                elem = elem || document;
                if (elem.cancelFullScrren) {
                    elem.cancelFullScrren();
                } else if (elem.mozCancelFullScreen) {
                    elem.mozCancelFullScreen();
                } else if (elem.webkitCancelFullScreen) {
                    elem.webkitCancelFullScreen();
                } else if (elem.msExitFullscreen) {
                    elem.msExitFullscreen();
                }
            }

            videoNode.addEventListener('ended', cancelFullScrren, false);


            /**
             * 播放完畢還原設置
             * videoNode.onended = function () {};在低版本上無效
             */

            videoNode.addEventListener("ended", function () {
                videoNode.pause();
                videoNode.currentTime = 0;
                media_bar[0].style.width = 0;
                media_play_stop.find("span")[0].className = "media-play";
                media_ico.show();

                /**
                 * 瀏覽器的用法
                 * 1.
                 * 進度條爲0  :
                 * media_bar[0].style.width = 0; 
                 * 還原當前播放時間 :
                 * media_current[0].innerHTML = getFormatTime();
                 * 視頻恢復到播放開始狀態:
                 * videoNode.currentTime = 0;
                 * 切換播放按鈕狀態:
                 * media_play[0].className = "media-play";
                 * 2.
                 * 或者:videoNode.load(); 但是視頻會跳一下,安卓下不適用
                 * 3.
                 * 所有通用用法
                   *videoNode.src = '';
                   *videoNode.src = data.src;
                   * media_bar[0].style.width = 0;
                   * media_current[0].innerHTML = getFormatTime();
                   * videoNode.currentTime = 0;
                  */
            });

            /**
             * 淡入淡出顯示隱藏播放欄
             */
            var fadeOut;
            ~function toggleSwitch() {
                //顯示
                panlParent.off("mouseenter").on("mouseenter", function () {
                    clearInterval(fadeOut);
                    media_controller.fadeIn(300);
                });
                //隱藏
                panlParent.off("mouseleave").on("mouseleave", function () {
                    fadeOut = setTimeout(function () {
                        media_controller.fadeOut(300);
                        media_speed_item.fadeOut(300);
                    }, 3000)
                });
            }()

            /**
             * 顯示播放速率
             */

            media_speed.off('click').click(function () {
                media_speed_item.toggle();
            })

            /**
            * 控制播放速率
            */
            var speedArry = [0.5, 1, 1.25, 1.5, 2.0];
            media_speed_item.off("click", 'li').on("click", 'li', function () {
                var index = $(this).index();
                videoNode.playbackRate = speedArry[index];
                media_speed_item.find("li").removeClass("active");
                $(this).addClass('active');
                media_speed_item.hide();
                return false;
            });
        }()


    } else {
        var panlParent = $("#" + id);
        panlParent.hide();
        alert("視頻路徑錯誤,播放失敗!");
    }
    return videoNode;
}

//時間
function getFormatTime(time) {
    var time = time || 0;
    var h = parseInt(time / 3600),
        m = parseInt(time % 3600 / 60),
        s = parseInt(time % 60);
    h = h < 10 ? "0" + h : h;
    m = m < 10 ? "0" + m : m;
    s = s < 10 ? "0" + s : s;
    return h + " : " + m + " : " + s;
}



/**
 * 調用方法
 *  
 *   html += ' <div class="details-video" id="details-video"> </div> ';
 *  comm_medias('details-video', { src: 'https://d-image.i4.cn/pubImg/mall/2019/04/19/11/1555643566349_616931.mp4' });
 * 
 */


最後 你再引入jq 或者 你想用js 就修改一下里面的獲取的方式 ,其他邏輯不變

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章