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 就修改一下里面的获取的方式 ,其他逻辑不变

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值