如何引入并初始化 Willes 手机播放器
html代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0"/> <title>HTML5手机播放器</title> <link rel="stylesheet" type="text/css" href="css/reset.css"/> <link rel="stylesheet" type="text/css" href="css/bootstrap.css"> <link rel="stylesheet" type="text/css" href="css/willesPlay.css"/> <script src="js/jquery.min.js"></script> <script src="js/willesPlay.js" type="text/javascript" charset="utf-8"></script> </head> <body> <div class="container"> <div class="row"> <div class="col-md-12"> <div id="willesPlay"> <div class="playHeader"> <div class="videoName">响应式设计</div> </div> <div class="playContent"> <div class="turnoff"> <ul> <li><a href="javascript:;" title="喜欢" class="glyphicon glyphicon-heart-empty"></a></li> <li><a href="javascript:;" title="关灯" class="btnLight on glyphicon glyphicon-sunglasses"></a></li> <li><a href="javascript:;" title="分享" class="glyphicon glyphicon-share"></a></li> </ul> </div> <video width="100%" height="100%" id="playVideo"> <source src="test.mp4" type="video/mp4"> </source> 当前浏览器不支持 video直接播放,点击这里下载视频: <a href="/">下载视频</a></video> <div class="playTip glyphicon glyphicon-play"></div> </div> <div class="playControll"> <div class="playPause playIcon"></div> <div class="timebar"><span class="currentTime">0:00:00</span> <div class="progress"> <div class="progress-bar progress-bar-danger progress-bar-striped" role="progressbar" aria-valuemin="0" aria-valuemax="100" style="width: 0%"></div> </div> <span class="duration">0:00:00</span></div> <div class="otherControl"><span class="volume glyphicon glyphicon-volume-down"></span> <span class="fullScreen glyphicon glyphicon-fullscreen"></span> <div class="volumeBar"> <div class="volumewrap"> <div class="progress"> <div class="progress-bar progress-bar-danger" role="progressbar" aria-valuemin="0" aria-valuemax="100" style="width: 8px;height: 40%;"></div> </div> </div> </div> </div> </div> </div> </div> </div> </div> </body> </html>
willesPlay.js代码:
$(function() {
var playVideo = $('video');
var playPause = $('.playPause'); //播放和暂停
var currentTime = $('.timebar .currentTime'); //当前时间
var duration = $('.timebar .duration'); //总时间
var progress = $('.timebar .progress-bar'); //进度条
var volumebar = $('.volumeBar .volumewrap').find('.progress-bar');
playVideo[0].volume = 0.4; //初始化音量
playPause.on('click', function() {
playControl();
});
$('.playContent').on('click', function() {
playControl();
}).hover(function() {
$('.turnoff').stop().animate({
'right': 0
}, 500);
}, function() {
$('.turnoff').stop().animate({
'right': -40
}, 500);
});
$(document).click(function() {
$('.volumeBar').hide();
});
playVideo.on('loadedmetadata', function() {
duration.text(formatSeconds(playVideo[0].duration));
});
playVideo.on('timeupdate', function() {
currentTime.text(formatSeconds(playVideo[0].currentTime));
progress.css('width', 100 * playVideo[0].currentTime / playVideo[0].duration + '%');
});
playVideo.on('ended', function() {
$('.playTip').removeClass('glyphicon-pause').addClass('glyphicon-play').fadeIn();
playPause.toggleClass('playIcon');
});
$(window).keyup(function(event){
event = event || window.event;
if(event.keyCode == 32)playControl();
if(event.keyCode == 27){
$('.fullScreen').removeClass('cancleScreen');
$('#willesPlay .playControll').css({
'bottom': -48
}).removeClass('fullControll');
};
event.preventDefault();
});
//全屏
$('.fullScreen').on('click', function() {
if ($(this).hasClass('cancleScreen')) {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozExitFullScreen) {
document.mozExitFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
}
$(this).removeClass('cancleScreen');
$('#willesPlay .playControll').css({
'bottom': -48
}).removeClass('fullControll');
} else {
if (playVideo[0].requestFullscreen) {
playVideo[0].requestFullscreen();
} else if (playVideo[0].mozRequestFullScreen) {
playVideo[0].mozRequestFullScreen();
} else if (playVideo[0].webkitRequestFullscreen) {
playVideo[0].webkitRequestFullscreen();
} else if (playVideo[0].msRequestFullscreen) {
playVideo[0].msRequestFullscreen();
}
$(this).addClass('cancleScreen');
$('#willesPlay .playControll').css({
'left': 0,
'bottom': 0
}).addClass('fullControll');
}
return false;
});
//音量
$('.volume').on('click', function(e) {
e = e || window.event;
$('.volumeBar').toggle();
e.stopPropagation();
});
$('.volumeBar').on('click mousewheel DOMMouseScroll', function(e) {
e = e || window.event;
volumeControl(e);
e.stopPropagation();
return false;
});
$('.timebar .progress').mousedown(function(e) {
e = e || window.event;
updatebar(e.pageX);
});
//$('.playContent').on('mousewheel DOMMouseScroll',function(e){
// volumeControl(e);
//});
var updatebar = function(x) {
var maxduration = playVideo[0].duration; //Video
var positions = x - progress.offset().left; //Click pos
var percentage = 100 * positions / $('.timebar .progress').width();
//Check within range
if (percentage > 100) {
percentage = 100;
}
if (percentage < 0) {
percentage = 0;
}
//Update progress bar and video currenttime
progress.css('width', percentage + '%');
playVideo[0].currentTime = maxduration * percentage / 100;
};
//音量控制
function volumeControl(e) {
e = e || window.event;
var eventype = e.type;
var delta = (e.originalEvent.wheelDelta && (e.originalEvent.wheelDelta > 0 ? 1 : -1)) || (e.originalEvent.detail && (e.originalEvent.detail > 0 ? -1 : 1));
var positions = 0;
var percentage = 0;
if (eventype == "click") {
positions = volumebar.offset().top - e.pageY;
percentage = 100 * (positions + volumebar.height()) / $('.volumeBar .volumewrap').height();
} else if (eventype == "mousewheel" || eventype == "DOMMouseScroll") {
percentage = 100 * (volumebar.height() + delta) / $('.volumeBar .volumewrap').height();
}
if (percentage < 0) {
percentage = 0;
$('.otherControl .volume').attr('class', 'volume glyphicon glyphicon-volume-off');
}
if (percentage > 50) {
$('.otherControl .volume').attr('class', 'volume glyphicon glyphicon-volume-up');
}
if (percentage > 0 && percentage <= 50) {
$('.otherControl .volume').attr('class', 'volume glyphicon glyphicon-volume-down');
}
if (percentage >= 100) {
percentage = 100;
}
$('.volumewrap .progress-bar').css('height', percentage + '%');
playVideo[0].volume = percentage / 100;
e.stopPropagation();
e.preventDefault();
}
function playControl() {
playPause.toggleClass('playIcon');
if (playVideo[0].paused) {
playVideo[0].play();
$('.playTip').removeClass('glyphicon-play').addClass('glyphicon-pause').fadeOut();
} else {
playVideo[0].pause();
$('.playTip').removeClass('glyphicon-pause').addClass('glyphicon-play').fadeIn();
}
}
//关灯
$('.btnLight').click(function(e) {
e = e || window.event;
if ($(this).hasClass('on')) {
$(this).removeClass('on');
$('body').append('<div class="overlay"></div>');
$('.overlay').css({
'position': 'absolute',
'width': 100 + '%',
'height': $(document).height(),
'background': '#000',
'opacity': 1,
'top': 0,
'left': 0,
'z-index': 999
});
$('.playContent').css({
'z-index': 1000
});
$('.playControll').css({
'bottom': -48,
'z-index': 1000
});
$('.playContent').hover(function() {
$('.playControll').stop().animate({
'height': 48,
},500);
}, function() {
setTimeout(function() {
$('.playControll').stop().animate({
'height': 0,
}, 500);
}, 2000)
});
} else {
$(this).addClass('on');
$('.overlay').remove();
$('.playControll').css({
'bottom': 0,
});
}
e.stopPropagation();
e.preventDefault();
});
});
//秒转时间
function formatSeconds(value) {
value = parseInt(value);
var time;
if (value > -1) {
hour = Math.floor(value / 3600);
min = Math.floor(value / 60) % 60;
sec = value % 60;
day = parseInt(hour / 24);
if (day > 0) {
hour = hour - 24 * day;
time = day + "day " + hour + ":";
} else time = hour + ":";
if (min < 10) {
time += "0";
}
time += min + ":";
if (sec < 10) {
time += "0";
}
time += sec;
}
return time;
}willesPlay.css代码:
@charset "utf-8";
html,body{
width: 100%;
height: 100%;
background: #ef6a6c;
}
a:hover{
text-decoration: none;
}
#willesPlay{
/*width: 1000px;
height: 660px;*/
/*width: 1024px;
height: auto;*/
margin: 100px auto;
box-shadow: 0px 0px 15px #333333;
position: relative;
}
/*播放器头部*/
#willesPlay .playHeader{
width: 100%;
height: 48px;
background: url(../img/playheader.jpg) repeat-x;
border-radius: 3px 3px 0px 0px;
}
#willesPlay .playHeader .videoName{
font-size: 16px;
width: 400px;
height: 48px;
line-height: 48px;
text-align: center;
margin: 0 auto;
color: #7a7f82;
}
#willesPlay .playContent{
position: relative;
height: auto;
overflow: hidden;
background:#000;
cursor: pointer;
}
#willesPlay .playContent .turnoff{
position: absolute;
z-index: 10;
right: -40px;
top: 50%;
margin-top: -90px;
}
#willesPlay .playContent .turnoff li a{
display: block;
width: 40px;
height: 40px;
line-height: 40px;
margin-bottom: 20px;
text-align: center;
font-size: 20px;
color: #fff;
background: rgba(0,0,0,.5);
}
#willesPlay .playContent .turnoff li a:hover{
color: #666;
}
#willesPlay .playContent .playTip{
position: absolute;
width: 110px;
height: 110px;
text-align: center;
line-height: 110px;
top: 50%;
left: 50%;
margin-left: -55px;
margin-top: -55px;
background: #ef6a6c;
font-size: 60px;
border: 3px solid #FFFFFF;
border-radius: 50%;
color: #fff;
cursor: pointer;
}
#willesPlay .playControll{
position: absolute;
z-index: 2147483650;
width: 100%;
height: 48px;
bottom: -48px;
background: url(../img/playheader.jpg) repeat-x;
border-radius: 0px 0px 3px 3px;
-moz-user-select:none;
-webkit-user-select:none;
user-select:none;
}
#willesPlay .fullControll{
background:rgba(0,0,0,.5);
}
#willesPlay .fullControll .timebar span{
color: #FFFFFF;
}
#willesPlay .playControll .playPause{
float: left;
width: 20px;
height: 25px;
background: url(../img/control_01.png) 0px 0px no-repeat;
margin: 11px 0px 0px 12px;
cursor: pointer;
}
#willesPlay .playControll .playIcon{
background-position: 0px -32px;
}
/*进度条*/
#willesPlay .playControll .timebar{
float: left;
width: calc(100% - 145px);
line-height: 48px;
overflow: hidden;
margin: 0 auto;
margin: 0px 0px 0px 20px;
}
#willesPlay .playControll .timebar .progress{
float: left;
width: 80%;
margin: 19px 5px;
height: 10px;
cursor: pointer;
}
#willesPlay .playControll .timebar span{
float: left;
width: 8%;
text-align: center;
}
#willesPlay .otherControl{
float: right;
position: relative;
}
#willesPlay .otherControl span{
display: inline-block;
width: 30px;
height: 30px;
text-align: center;
line-height: 30px;
vertical-align: middle;
font-size: 20px;
margin: 9px 7px;
/*background: url(../images/control_01.png) no-repeat;*/
cursor: pointer;
}
#willesPlay .otherControl span:nth-child(1){
font-size: 28px;
color: #ef6a6c;
}
/*#willesPlay .otherControl span:nth-child(2){
background-position: -171px 0px;
}*/
#willesPlay .otherControl span:nth-child(2){
color: #919597;
}
/*音量*/
#willesPlay .otherControl .volumeBar{
display: none;
position: absolute;
top: -110px;
left:4px;
width: 26px;
height: 100px;
background:#f1f2f2;
border-radius: 4px;
cursor: pointer;
}
#willesPlay .otherControl .volumeBar:after{
content:"";
display: block;
position:absolute;
bottom: -7px;
left: 5px;
width: 0;
height: 0;
border-left:8px solid transparent;
border-right: 8px solid transparent;
border-top: 8px solid #f1f2f2;
}
#willesPlay .otherControl .volumeBar .volumewrap{
background: #a2a7aa;
width: 8px;
height: 80px;
position: absolute;
bottom: 10px;
left: 9px;
border-radius: 4px;
}
#willesPlay .otherControl .volumeBar .progress{
background: none;
}
#willesPlay .otherControl .volumeBar .progress-bar{
position: absolute;
bottom: 0px;
left: 0px;
border-radius: 4px;
}
video::-webkit-media-controls-enclosure {
/*禁用播放器控制栏的样式*/
display: none !important;
}
:-webkit-full-screen{}下面我来详细讲解这个代码是如何引入并初始化 Willes 手机播放器的。
一、HTML 中的引入方式
1. CSS 样式引入(第 9-11 行)
html
<link rel="stylesheet" type="text/css" href="css/reset.css"/><link rel="stylesheet" type="text/css" href="css/bootstrap.css"><link rel="stylesheet" type="text/css" href="css/willesPlay.css"/>
第9行:引入
reset.css- 重置浏览器默认样式,保证跨浏览器一致性第10行:引入
bootstrap.css- Bootstrap 框架样式,提供响应式布局支持第11行:引入
willesPlay.css- 核心样式文件,定义了播放器的外观(控制栏、进度条、按钮等)
2. JavaScript 脚本引入(第 12-13 行)
html
<script src="js/jquery.min.js"></script><script src="js/willesPlay.js" type="text/javascript" charset="utf-8"></script>
第12行:引入 jQuery 库(Willes 播放器依赖 jQuery)
第13行:核心脚本文件
willesPlay.js- 包含播放器所有交互逻辑
二、播放器 DOM 结构(第 17-51 行)
html
<div id="willesPlay"> <!-- 播放器容器,ID用于CSS和JS定位 --> <div class="playHeader"> <!-- 头部区域:显示视频标题 --> <div class="videoName">响应式设计</div> </div> <div class="playContent"> <!-- 视频播放区域 --> <div class="turnoff">...</div> <!-- 右上角功能按钮区(喜欢、关灯、分享)--> <video width="100%" height="100%" id="playVideo"> <!-- 原生video标签 --> <source src="test.mp4" type="video/mp4"> </video> <div class="playTip glyphicon glyphicon-play"></div> <!-- 中央播放按钮 --> </div> <div class="playControll"> <!-- 底部控制栏 --> <div class="playPause playIcon"></div> <!-- 播放/暂停按钮 --> <div class="timebar"> <!-- 时间进度区域 --> <span class="currentTime">0:00:00</span> <!-- 当前时间 --> <div class="progress"> <!-- 进度条容器 --> <div class="progress-bar..."></div> <!-- 进度条填充 --> </div> <span class="duration">0:00:00</span> <!-- 总时长 --> </div> <div class="otherControl"> <!-- 其他控制按钮 --> <span class="volume..."></span> <!-- 音量图标 --> <span class="fullScreen..."></span> <!-- 全屏按钮 --> <div class="volumeBar">...</div> <!-- 音量调节条 --> </div> </div></div>
三、willesPlay.js 核心代码逐行讲解
初始化阶段(第 1-6 行)
javascript
$(function() { // jQuery 文档就绪事件,DOM加载完成后执行
var playVideo = $('video'); // 获取video元素
var playPause = $('.playPause'); // 播放/暂停按钮
var currentTime = $('.timebar .currentTime'); // 当前时间显示
var duration = $('.timebar .duration'); // 总时长显示
var progress = $('.timebar .progress-bar'); // 进度条
var volumebar = $('.volumeBar .volumewrap').find('.progress-bar'); // 音量条
playVideo[0].volume = 0.4; // 设置初始音量为40%(0.4)播放控制(第 7-15 行)
javascript
playPause.on('click', function() { // 点击播放/暂停按钮
playControl(); // 调用播放控制函数
});
$('.playContent').on('click', function() { // 点击视频画面区域
playControl(); // 同样触发播放/暂停
}).hover(function() { // 鼠标悬停时
$('.turnoff').stop().animate({'right': 0}, 500); // 显示右上角按钮(从右滑入)
}, function() { // 鼠标离开时
$('.turnoff').stop().animate({'right': -40}, 500); // 隐藏右上角按钮(滑出)
});视频元数据加载(第 19-21 行)
javascript
playVideo.on('loadedmetadata', function() { // 视频元数据加载完成事件
duration.text(formatSeconds(playVideo[0].duration)); // 显示总时长(秒转时间格式)
});播放进度更新(第 23-27 行)
javascript
playVideo.on('timeupdate', function() { // 播放时间更新事件(每秒触发多次)
currentTime.text(formatSeconds(playVideo[0].currentTime)); // 更新当前时间
progress.css('width', 100 * playVideo[0].currentTime / playVideo[0].duration + '%');
// 计算播放进度百分比并设置进度条宽度
});播放结束处理(第 28-30 行)
javascript
playVideo.on('ended', function() { // 视频播放结束事件
$('.playTip').removeClass('glyphicon-pause').addClass('glyphicon-play').fadeIn();
// 中央图标从暂停改为播放并显示
playPause.toggleClass('playIcon'); // 切换底部按钮样式
});全屏功能(第 47-78 行)
javascript
$('.fullScreen').on('click', function() { // 点击全屏按钮
if ($(this).hasClass('cancleScreen')) { // 如果是退出全屏状态
// 退出全屏(兼容不同浏览器)
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozExitFullScreen) {
document.mozExitFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
}
$(this).removeClass('cancleScreen'); // 移除退出全屏标识
} else { // 进入全屏
// 请求全屏(兼容各浏览器)
if (playVideo[0].requestFullscreen) {
playVideo[0].requestFullscreen();
} else if (playVideo[0].mozRequestFullScreen) {
playVideo[0].mozRequestFullScreen();
} else if (playVideo[0].webkitRequestFullscreen) {
playVideo[0].webkitRequestFullscreen();
}
$(this).addClass('cancleScreen'); // 添加退出全屏标识
}
});核心播放控制函数(第 135-145 行)
javascript
function playControl() { // 播放/暂停核心逻辑
playPause.toggleClass('playIcon'); // 切换底部按钮图标样式
if (playVideo[0].paused) { // 如果视频是暂停状态
playVideo[0].play(); // 播放视频
$('.playTip').removeClass('glyphicon-play').addClass('glyphicon-pause').fadeOut();
// 中央图标从播放改为暂停并淡出
} else { // 如果视频是播放状态
playVideo[0].pause(); // 暂停视频
$('.playTip').removeClass('glyphicon-pause').addClass('glyphicon-play').fadeIn();
// 中央图标从暂停改为播放并淡入
}
}时间格式化函数(第 156-178 行)
javascript
function formatSeconds(value) { // 将秒数转换为 HH:MM:SS 格式
value = parseInt(value);
var time;
hour = Math.floor(value / 3600); // 计算小时
min = Math.floor(value / 60) % 60; // 计算分钟
sec = value % 60; // 计算秒数
time = hour + ":"; // 拼接小时部分
if (min < 10) time += "0"; // 分钟补零
time += min + ":";
if (sec < 10) time += "0"; // 秒数补零
time += sec;
return time;}总结
Willes 播放器的引入流程:
HTML 结构:通过特定 class 和 id 构建播放器骨架
CSS 引入:
willesPlay.css提供样式和响应式布局JS 引入:
willesPlay.js依赖 jQuery,实现完整的播放控制逻辑核心机制:对原生
<video>标签进行封装,通过事件监听(timeupdate、loadedmetadata、ended)和控制函数(playControl、volumeControl)实现交互