> 此自定義播放器基於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 就修改一下里面的獲取的方式 ,其他邏輯不變