基于HTML5实现的视频播放器

2016年08月16日 18:21 0 点赞 0 评论 更新于 2025-11-21 20:05

关于hivideo

近期,我在使用PhoneGap开发一款App应用,该应用需要具备视频播放功能。起初,我打算直接采用HTML5的<video>标签来实现,但在实际使用中发现,其在全屏播放时不支持横屏,因此只能放弃这一方案。为了便于后续功能扩展,我决定自行封装一个视频播放器,并将其命名为“hivideo”。

hivideo是一款基于HTML5的视频播放器,它摒弃了原生<video>标签的播放控制条样式,重新进行了设计。该播放器支持暂停、播放进度控制、声音控制以及全屏播放等功能。若在手机端使用,全屏播放时还支持横屏显示。

hivideo最终实现的效果如下:

如何使用hivideo

hivideo目录结构

assets
----images
----hivideo.css
hivideo.js

引入文件

要使用hivideo,首先需要在主界面引入样式文件hivideo.css

<link rel="stylesheet" href="assets/hivideo.css" />

hivideo.js文件既可以在主页面直接引用,也支持CommonJS和AMD规范。

转换为hivideo播放器

在需要转换为hivideo播放器的<video>标签上添加ishivideo="true"属性,hivideo会自动将该<video>元素转换为hivideo播放器。示例如下:

<video ishivideo="true"></video>

同时,我们还可以在<video>标签上设置以下播放属性:

  • autoplay:设置为true时,视频将自动播放。
  • isrotate:若在手机端使用hivideo,将该属性设置为true,表示全屏播放时横屏显示。
  • autoHide:设置为true时,播放视频时将自动隐藏控制条。

使用示例:

<video ishivideo="true" autoplay="true" isrotate="false" autoHide="true">
<source src="http://www.html5videoplayer.net/videos/madagascar3.mp4" type="video/mp4">
</video>

动态加载

如果是后期动态添加的<video>元素,也可以通过hivideo进行动态加载。例如,页面动态添加了一个idplayer<video>元素,可通过以下方式将其转换为hivideo播放器:

hivideo(document.getElementById("player"));

如何隐藏浏览器的播放器样式

目前,大多数浏览器都支持<video>元素,但不同浏览器实现的<video>样式存在差异。为了让播放器在各个浏览器下样式统一,需要先隐藏各个浏览器自带的样式。

然而,一般通过浏览器开发工具无法直接查看播放器下的元素,因为这些元素属于阴影元素(Shadow DOM),它们是通过文档片段附加到<video>上的,对于文档流是不可见的。

在Chrome浏览器中,我们可以通过以下步骤查看阴影元素:打开开发者工具 -> Settings -> General页签,在Elements中找到“Show user agent shadow DOM”选项并勾选。勾选后,通过开发工具即可查看到<video>下的播放元素。

其中,<div pseudo="-webkit-media-controls">元素是控制条的容器,我们只需将其display属性设置为none,即可隐藏控制条。不过,需要兼容各个浏览器,具体样式代码如下:

video[ishivideo="true"]::-webkit-media-controls {
display: none !important;
}
video[ishivideo="true"]::-moz-media-controls {
display: none !important;
}
video[ishivideo="true"]::-o-media-controls {
display: none !important;
}
video[ishivideo="true"]::media-controls {
display: none !important;
}

需要注意的是,将上述样式通过合并的方式书写是无效的,以下写法不能隐藏阴影元素:

video[ishivideo="true"]::-webkit-media-controls,
video[ishivideo="true"]::-moz-media-controls,
video[ishivideo="true"]::-o-media-controls,
video[ishivideo="true"]::media-controls {
display: none !important;
}

隐藏浏览器阴影元素后,就可以开始实现自定义控制条了。在实现之前,我们需要了解<video>标签提供的API。

播放器常用API

各个浏览器操作播放器提供的API名称通常带有厂商前缀,因此基本上每个API函数都对应多个版本,需要考虑兼容性。以下是一些常用的API:

1. 全屏事件

["fullscreenchange", "webkitfullscreenchange", "mozfullscreenchange", "MSFullscreenChange"].forEach(function(eventType) {
document.addEventListener(eventType, function(event) {
// 处理全屏状态变化事件
});
});

当播放器全屏状态发生变化时,上述事件会被触发。但仅通过该事件,我们只能知道全屏状态发生了改变,无法确定当前是进入全屏还是退出全屏,还需要结合全屏状态API进行判断。

2. 当前是否全屏状态

hivideo.prototype.isFullScreen = function() {
return document.fullscreenElement ||
document.webkitFullscreenElement ||
document.mozFullScreenElement ||
document.msFullscreenElement;
};

上述代码是hivideo封装的判断是否全屏的函数。

3. 进入全屏模式

if (video.requestFullscreen) {
video.requestFullscreen();
} else if (video.webkitRequestFullscreen) {
video.webkitRequestFullscreen();
} else if (video.mozRequestFullScreen) {
video.mozRequestFullScreen();
} else if (video.msRequestFullscreen) {
video.msRequestFullscreen();
}

4. 退出全屏模式

if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}

5. 播放状态

video.paused属性用于判断视频的播放状态,true表示未播放,false表示正在播放。

6. 播放视频

video.play();

7. 暂停播放

video.pause();

8. 是否静音

video.muted = true; // 静音
video.muted = false; // 不静音

9. 声音控制

通过设置video.volume属性来控制声音大小,其值的范围为0到1。

10. 当前播放时间

video.currentTime属性可读可写,单位为秒。可以通过<input type='range'>的值来显示播放进度。

11. 视频总时长

video.duration属性表示视频的总时长,单位为秒。

12. 播放时间更新事件

video.addEventListener("timeupdate", function() {
// 处理播放时间更新事件
});

13. 视频元数据加载完成事件

一般在播放视频时会显示视频总时长,当触发loadedmetadata事件时,视频元数据已经加载完成,因此可以在该事件中设置总时长的显示。

video.addEventListener("loadedmetadata", function() {
// 处理视频元数据加载完成事件
});

14. 视频播放结束事件

video.addEventListener("ended", function() {
// 处理视频播放结束事件
});

有了上述API,实现自定义播放器就相对容易了,在实现过程中,只需在相应位置调用对应的API即可。

如何实现横屏播放

实现横屏播放的原理较为简单,在全屏时,播放器容器会占据整个屏幕。我们可以为容器添加一个自定义样式,使其旋转90度。示例样式如下:

.rotate90 {
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
-ms-transform: rotate(90deg);
-o-transform: rotate(90deg);
transform: rotate(90deg);
}

旋转后的容器宽度和高度需要进行调整,将屏幕的高度screen.height赋值给容器的宽度,将屏幕的宽度赋值给容器的高度,这样就能实现全屏横屏播放效果。以下是全屏播放控制的完整代码:

hivideo.prototype.bindFullEvent = function() {
var self = this;
var origWidth = origHeight = 0;

["fullscreenchange", "webkitfullscreenchange", "mozfullscreenchange", "MSFullscreenChange"].forEach(function(eventType) {
var curFullhivideoId = null;
document.addEventListener(eventType, function(event) {
if ((curFullhivideoId = document.body.getAttribute("curfullHivideo")) && curFullhivideoId !== self.videoId_) {
return;
}
var isRotate = self.options.isrotate;
if (self.isFullScreen()) {
var cltHeight = isRotate ? window.screen.width : window.screen.height;
var cltWidth = isRotate ? window.screen.height : window.screen.width;
if (isRotate && !hivideo.hasClass(self.videoParent, "rotate90")) {
hivideo.addClass(self.videoParent, "rotate90");
}
self.videoParent.style.height = cltHeight + "px";
self.videoParent.style.width = cltWidth + "px";
} else {
if (isRotate) {
self.videoParent.className = self.videoParent.className.replace("rotate90", "").trim();
}
self.videoParent.style.height = origHeight + "px";
self.videoParent.style.width = origWidth + "px";
}
});
});

self.fullBtn && self.fullBtn.addEventListener("click", function() {
if (!self.isFullScreen()) {
document.body.setAttribute("curfullHivideo", self.videoId_);
origWidth = self.videoParent.offsetWidth;
origHeight = self.videoParent.offsetHeight;
// 进入全屏
if (self.videoParent.requestFullscreen) {
self.videoParent.requestFullscreen();
} else if (self.videoParent.webkitRequestFullscreen) {
self.videoParent.webkitRequestFullscreen();
} else if (self.videoParent.mozRequestFullScreen) {
self.videoParent.mozRequestFullScreen();
} else if (self.videoParent.msRequestFullscreen) {
self.videoParent.msRequestFullscreen();
}
self.exchangeBtnStatus(this, false);
} else {
// 退出全屏
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
self.exchangeBtnStatus(this, true);
}
});

return self;
};

支持CommonJS、AMD规范

1. CommonJS支持

(function(global, factory) {
"use strict";
// 支持CommonJS规范
if (typeof module === "object" && typeof module.exports === "object") {
module.exports = factory(global);
} else {
factory(global);
}
}(typeof window !== "undefined" ? window : this, function(window) {
// 具体实现代码
}));

2. AMD支持

// 支持AMD规范
if (typeof define === "function" && define.amd) {
define("hivideo", [], function() {
return hivideo;
});
}

大家觉得有帮助请关注“泰斗社区”了解更多相关资讯。