此文章是接着上次写的《酷炫视频播放器制作_界面篇》将其完善,我们主要给大家介绍一下如何利用JS脚本来控制视频的播放。为了让大家能够保持对要完成的功能有直接的了解,我们还是将效果图附到文章里面

完成本篇文章的代码编写,你能GET到200+代码量,且能够掌握很多有关video标签的属性,函数,事件的应用。当然希望大家也多多鼓励我写出更多更实际的文章来帮助大家学习的提升

第一步:我们先简单实现播放与暂停的效果,为了整个界面的DOM操作简单一点,我们就用jQuery来配合界面的操作

$(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();
}); /**
* 控制播放的函数
*/
function playControl() {
// 切换播放按钮的样式
playPause.toggleClass('playIcon');
if(playVideo[0].paused) {
playVideo[0].play();
} else {
playVideo[0].pause();
}
}
});

第二步:计算视频时长,时长的显示标准:小时:分钟:妙。这里我们会H5中video标签的duration属性,此属性返回视频的时长,时长计量单位秒

/**
* 将视频时长转化为时间:小时,分钟,秒
* @param {Object} value
*/
function formatSeconds(value) {
value = parseInt(value);
var time; // 存储转化好的时间格式
if(value > -1) {
hour = Math.floor(value / 3600); // 1小时=3600秒
min = Math.floor(value / 60) % 60; // 1分钟=60秒
sec = value % 60;
day = parseInt(hour / 24);
if(day > 0) {
hour = hour - 24 * day;
time = day + "day " + hour + ":";
} else {
time = hour + ":";
}
if (min < 0) {
time += "0"
}
time += min + ":";
if (sec < 0) {
time += "0";
}
time += sec;
}
return time;
}

第三步:设置视频加载后将视频时长显示到页面上。这里会用到video标签的onloadedmetadata事件

/**
* 视频加载结束后触发loadedmetadata事件
* onloadedmetadata 事件在指定视频/音频(audio/video)的元数据加载后触发
* 视频/音频(audio/video)的元数据包含: 时长,尺寸大小(视频),文本轨道
*/
playVideo.on("loadedmetadata", function() {
duration.text(formatSeconds(playVideo[0].duration));
});

第四步:视频进度条更新,完成视频播放时候进度条不断加载播放进度。这里会用到video标签的timeupdate事件

/**
* ontimeupdate 事件在视频/音频(audio/video)当前的播放位置发送改变时触发
* 该事件通常与 Video 对象的 currentTime 属性一起使用, 该属性返回视频/音频(audio/video)的当前播放位置
*/
playVideo.on("timeupdate", function() {
currentTime.text(formatSeconds(playVideo[0].currentTime));
progress.css("width", 100 * playVideo[0].currentTime / playVideo[0].duration + "%");
});

第五步:视频播放完成需要完成的更新操作。这里会用到video标签的ended事件

/**
* ended 事件在音频/视频(audio/video)播放完成后触发
*/
playVideo.on('ended', function() {
playPause.toggleClass('playIcon');
});

第六步:视频全屏播放,这里考虑兼容不同浏览器的内核(webkit,moz,ie)。同时还会用到video标签的requestFullscreen属性来判断全屏模式,document元素的exitFullScreen来退出全屏等功能设置

/**
* 视频全屏播放
* 这里尽量做到IE,Chrome,moz的内核的浏览器全屏播放的兼容性
*/
$('.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;
});

第七步:调整播放进度代码实现,思路如下

  • 通过offset().left获取进度条的坐标位置
  • 通过鼠标点击进度条坐标-进度条初始坐标位置=拉动进度条的偏移量(真实拉动距离)
  • 最后计算进度条的百分比,然后再转化为视频拉动的时间
/**
* 拉动时间轴,调整播放的进度
*/
$(".timebar .progress").mousedown(function(e) {
e = e || window.event;
updatebar(e.pageX);
}); /**
* 调整播放进度代码实现
* 通过offset().left获取进度条的坐标位置
* 通过鼠标点击进度条坐标-进度条初始坐标位置=拉动进度条的偏移量(真实拉动距离)
* 最后计算进度条的百分比,然后再转化为视频拉动的时间
*/
var updatebar = function(x) {
var maxduration = playVideo[0].duration; // 总时长
var positions = x - progress.offset().left; // 拉动进度条的偏移量
var percentage = 100 * positions / $(".timebar .progress").width();
if(percentage > 100) {
percentage = 100;
}
if (percentage < 0) {
percentage = 0;
}
progress.css("width", percentage + "%");
playVideo[0].currentTime = maxduration * percentage / 100;
}

第八步:音量调整与控制

/**
* 音量控制弹出窗
*/
$(".volume").on("click", function(e) {
e = e || window.event;
$(".volumeBar").toggle();
e.stopPropagation();
}); /**
* 音量控制事件监听
* 多事件绑定:点击,鼠标滚轮等等方式来操作音量控制
*/
$(".volumeBar").on('click mousewhell DOMMouseScroll', function(e){
e = e || window.event;
volumeControl(e); // 控制音量调整的核心代码
e.stopPropagation();
return false;
}); /**
* 控制音量调整的核心代码
* @param {Object} e
*/
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() {
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();
formatSeconds(playVideo[0].duration);
}); /**
* 控制播放的函数
*/
function playControl() {
// 切换播放按钮的样式
playPause.toggleClass('playIcon');
if(playVideo[0].paused) {
playVideo[0].play();
} else {
playVideo[0].pause();
}
} /**
* 点击网页任何地方让音量调节窗口关闭
*/
$(document).click(function() {
$(".volumeBar").hide();
}); /**
* 视频加载结束后触发loadedmetadata事件
* onloadedmetadata 事件在指定视频/音频(audio/video)的元数据加载后触发
* 视频/音频(audio/video)的元数据包含: 时长,尺寸大小(视频),文本轨道
*/
playVideo.on("loadedmetadata", function() {
duration.text(formatSeconds(playVideo[0].duration));
}); /**
* ontimeupdate 事件在视频/音频(audio/video)当前的播放位置发送改变时触发
* 该事件通常与 Video 对象的 currentTime 属性一起使用, 该属性返回视频/音频(audio/video)的当前播放位置
*/
playVideo.on("timeupdate", function() {
currentTime.text(formatSeconds(playVideo[0].currentTime));
progress.css("width", 100 * playVideo[0].currentTime / playVideo[0].duration + "%");
}); /**
* ended 事件在音频/视频(audio/video)播放完成后触发
*/
playVideo.on('ended', function() {
playPause.toggleClass('playIcon');
}); /**
* 视频全屏播放
* 这里尽量做到IE,Chrome,moz的内核的浏览器全屏播放的兼容性
*/
$('.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;
}); /**
* 拉动时间轴,调整播放的进度
*/
$(".timebar .progress").mousedown(function(e) {
e = e || window.event;
updatebar(e.pageX);
}); /**
* 调整播放进度代码实现
* 通过offset().left获取进度条的坐标位置
* 通过鼠标点击进度条坐标-进度条初始坐标位置=拉动进度条的偏移量(真实拉动距离)
* 最后计算进度条的百分比,然后再转化为视频拉动的时间
*/
var updatebar = function(x) {
var maxduration = playVideo[0].duration; // 总时长
var positions = x - progress.offset().left; // 拉动进度条的偏移量
var percentage = 100 * positions / $(".timebar .progress").width();
if(percentage > 100) {
percentage = 100;
}
if (percentage < 0) {
percentage = 0;
}
progress.css("width", percentage + "%");
playVideo[0].currentTime = maxduration * percentage / 100;
} /**
* 音量控制弹出窗
*/
$(".volume").on("click", function(e) {
e = e || window.event;
$(".volumeBar").toggle();
e.stopPropagation();
}); /**
* 音量控制事件监听
* 多事件绑定:点击,鼠标滚轮等等方式来操作音量控制
*/
$(".volumeBar").on('click mousewhell DOMMouseScroll', function(e){
e = e || window.event;
volumeControl(e); // 控制音量调整的核心代码
e.stopPropagation();
return false;
}); /**
* 控制音量调整的核心代码
* @param {Object} e
*/
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();
}
}); /**
* 将视频时长转化为时间:小时,分钟,秒
* @param {Object} value
*/
function formatSeconds(value) {
value = parseInt(value);
var time; // 存储转化好的时间格式
if(value > -1) {
hour = Math.floor(value / 3600); // 1小时=3600秒
min = Math.floor(value / 60) % 60; // 1分钟=60秒
sec = value % 60;
day = parseInt(hour / 24);
if(day > 0) {
hour = hour - 24 * day;
time = day + "day " + hour + ":";
} else {
time = hour + ":";
}
if (min < 0) {
time += "0"
}
time += min + ":";
if (sec < 0) {
time += "0";
}
time += sec;
}
return time;
}

[刘阳Java]_酷炫视频播放器制作_JS篇的更多相关文章

  1. [刘阳Java]_酷炫视频播放器制作_界面篇

    今天开始分享一篇酷炫播放器制作,包括界面+JS.整个案例非常类似腾讯视频,优酷视频,爱奇艺视频.我们先看一下效果图,然后这篇文章主要界面篇 是不是效果比较酷炫,那么我接着来给大家说一下这个界面设计思路 ...

  2. [刘阳Java]_纯CSS代码实现内容过滤效果

    继续我们技术专题课,我们今天给大家带来的是一个比较酷炫的"纯CSS代码实现内容过滤效果",没有加入任何JS的效果.全部都是应用CSS3的新增选择器来实现的.先看效果截图 实现思路 ...

  3. [刘阳Java]_快速搭建MyBatis环境_第2讲

    1.MyBatis的环境配置 导入MyBatis包, mybatis-3.2.8.jar 导入MySQL驱动包, mysql-connector-java-5.1.24-bin.jar 创建表的实体类 ...

  4. [刘阳Java]_什么是MyBatis_第1讲

    1.什么MyBatis,我们先通过百度百科先进行一个简单的了解 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation ...

  5. [刘阳Java]_斗胆介绍一下Eclipse快捷键大全[超详细]_第6讲

    斗胆让我在这里介绍一下Eclipse快捷键有哪些 ctrl+shirt+r 打开资源 这组快捷键可以让你开打Eclipse工作区中任何一个文件,你只需要输入你想查找的文件名字即可,而且绝对支持模糊检索 ...

  6. [刘阳Java]_避开环境配置快速的使用Java的开发工具_第5讲

    我们一般学习Java都应该遵循通过系统的命令工具来编译Java程序,然后对编译好Java程序进行运行,这个是非常好的习惯.但是随着后期学习Java技术的深入我们也得像Java的IDE工具屈服.所以,可 ...

  7. [刘阳Java]_为什么要前后端分离

    前后端分离已成为互联网项目开发的业界标准使用方式,通过nginx+tomcat的方式(也可以中间加一个nodejs)有效的进行解耦,并且前后端分离会为以后的大型分布式架构.弹性计算架构.微服务架构.多 ...

  8. [刘阳Java]_程序员Java编程进阶的5个注意点,别编程两三年还是增删改查

    此文章也是关注网上好几篇技术文章后,今天分享出来.因为,总有在程序学习路上的小伙伴会感到迷茫.而迷茫存在的情况如下 第一种:在大学学习中出现的迷茫,不知道Java到底要学什么.学习Java的标准是什么 ...

  9. [刘阳Java]_第一个Java程序_第7讲

    1. 其实第一个Java程序是很简单,但是当自己编写第一个Java程序时候需要注意如下几个内容: 理解Java程序的运行环境 校验你的Java环境变量是否能够运行你所写的第一个Java程序 理解Jav ...

随机推荐

  1. tensorflow-yolov4实施方法

    tensorflow-yolov4实施方法 tensorflow-yolov4-tflite YOLOv4: Optimal Speed and Accuracy of Object Detectio ...

  2. Windows下Qt VS 打包程序 到他人电脑安装运行出现的问题

    1.可能缺程序依赖的Qt动态库   ------>    使用Qt自带的windeployqt进入安装程序所在的文件夹内进行自动配置 将程序安装在C盘之外的盘,这样可以方便windeployqt ...

  3. B-Tree插入和删除的Java实现

    B-Tree插入和删除的Java实现 一.一颗非空m阶B-Tree的性质 除根结点以外的每个结点的孩子引用最多存在m个,关键码最多存在m - 1个:除根结点以外的每个结点的孩子引用至少存在⌈m / 2 ...

  4. 强化学习之CartPole

    0x00 任务   通过强化学习算法完成倒立摆任务,控制倒立摆在一定范围内摆动. 0x01 设置jupyter登录密码 jupyter notebook --generate-config jupyt ...

  5. P1045 [NOIP2003 普及组] 麦森数

    题目描述 形如2^P−1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2^P−1不一定也是素数. 到1998年底,人们已找到了37个麦森数.最大的一个是P=3021377, ...

  6. 【NX二次开发】Block UI 超级点

    属性说明 属性   类型   描述   常规           BlockID    String    控件ID    Enable    Logical    是否可操作    Group    ...

  7. 【NX二次开发】缝合片体例子UF_MODL_create_sew

    缝合片体,没有成功缝合的片体涂绿色. 效果:  源码: extern DllExport void ufusr(char *param, int *returnCode, int rlen) { UF ...

  8. 【C++】Vector排序

    1.普通类型(由大到小排序) int main() { sort(v.begin(),v.end()); } 2.普通类型(由小到大排序) bool comp(const int &a,con ...

  9. Servlet--核心内容汇总

    Servlet汇总 因为看公司代码,有个cookie+jwt.Token登录验证接口,于是回顾下servlet.cookie.session.前后端分离restful.jwt.token相关内容.虽然 ...

  10. 魔镜魔镜,今天有雨吗?——GitHub 热点速览 v.21.25

    作者:HelloGitHub-小鱼干 上周智能驾驶项目的作者曾经做过一个透明小电视机,同透明电视机类似 MagicMirror 也是一个神奇的智能项目,使用它进行模块定制开发,你将拥有一块非常酷炫的智 ...