本文使用的都是CSS3以及html5中的video实现的播放器,在PC与手机端都可以完美播放,目前还未实现播放进度条的拖移功能,后续会增加这个功能。
demo效果查看地址:https://king2088.github.io/html5-vPlayer/
先看效果图:
首先我们要了解一下html5中的media事件以及属性
1、html5 Media api
*loadstart
*progress
*suspend
*abort
*error
*emptied
*stalled
*loadedmetadata
*loadeddata
*canplay
*canplaythrough
*playing
*waiting
*seeking
*seeked
*ended
*durationchange
*timeupdate
*play
*pause
*ratechange
*resize
*volumechange
2、Media properties
[cc lang=”javascript”][ “error”, “src”, “srcObject”, “currentSrc”, “crossOrigin”, “networkState”, “preload”, “buffered”, “readyState”, “seeking”, “currentTime”, “duration”, “paused”, “defaultPlaybackRate”, “playbackRate”, “played”, “seekable”, “ended”, “autoplay”, “loop”, “controls”, “volume”, “muted”, “defaultMuted”, “audioTracks”, “videoTracks”, “textTracks”, “width”, “height”, “videoWidth”, “videoHeight”, “poster” ][/cc]
3、CSS部分代码
[cc lang=”css”]*,
html,
body,
video {
margin: 0;
padding: 0;
}
* #vPlayer,
html #vPlayer,
body #vPlayer,
video #vPlayer {
width: 100%;
background: #000;
position: relative;
overflow: hidden;
}
* #playerContent,
html #playerContent,
body #playerContent,
video #playerContent {
width: 100%;
background: #000;
display: block;
}
* #playerControler,
html #playerControler,
body #playerControler,
video #playerControler {
width: 100%;
z-index: 99999999;
position: absolute;
bottom: 2px;
left: 0;
padding: 4px 0;
opacity: 1;
}
* #playerControler:after,
html #playerControler:after,
body #playerControler:after,
video #playerControler:after {
content: ”;
display: block;
height: 0;
clear: both;
}
* #playerControler .playButtonWrap,
html #playerControler .playButtonWrap,
body #playerControler .playButtonWrap,
video #playerControler .playButtonWrap {
width: 24px;
height: 24px;
border-radius: 14px;
border: 2px #ccc solid;
margin-left: 8px;
float: left;
}
* #playerControler .playButtonWrap .playButton,
html #playerControler .playButtonWrap .playButton,
body #playerControler .playButtonWrap .playButton,
video #playerControler .playButtonWrap .playButton {
margin: 4px 0 0 8px;
width: 0;
height: 0;
border-bottom: 8px solid transparent;
border-top: 8px solid transparent;
border-left: 10px solid #ccc;
}
* #playerControler .playButtonWrap .pauseButton,
html #playerControler .playButtonWrap .pauseButton,
body #playerControler .playButtonWrap .pauseButton,
video #playerControler .playButtonWrap .pauseButton {
margin: 6px 0 0 8px;
width: 5px;
height: 12px;
border-left: 2px #ccc solid;
border-right: 2px #ccc solid;
display: none;
}
* #playerControler #vplayerTimeLine,
html #playerControler #vplayerTimeLine,
body #playerControler #vplayerTimeLine,
video #playerControler #vplayerTimeLine {
color: #ccc;
line-height: 30px;
font-size: 12px;
float: left;
margin-left: 2%;
}
* #playerControler .vPlayVolumeWrap,
html #playerControler .vPlayVolumeWrap,
body #playerControler .vPlayVolumeWrap,
video #playerControler .vPlayVolumeWrap {
float: right;
margin: 6px 10% 0 0;
width: 25%;
}
* #playerControler .vPlayVolumeWrap #volumeIcon,
html #playerControler .vPlayVolumeWrap #volumeIcon,
body #playerControler .vPlayVolumeWrap #volumeIcon,
video #playerControler .vPlayVolumeWrap #volumeIcon {
width: 0px;
height: 0px;
padding: 5px 3px;
border-width: 5px 10px 5px 0px;
border-color: transparent #ccc transparent transparent;
border-style: solid;
/*喇叭效果*/
-webkit-box-shadow: inset 15px 0 #666;
-moz-box-shadow: inset 15px 0 #666;
box-shadow: inset 15px 0 #666;
float: left;
display: inline-block;
}
* #playerControler .vPlayVolumeWrap #vPlayVolume,
html #playerControler .vPlayVolumeWrap #vPlayVolume,
body #playerControler .vPlayVolumeWrap #vPlayVolume,
video #playerControler .vPlayVolumeWrap #vPlayVolume {
width: 70%;
height: 2px;
background: #ccc;
position: relative;
float: left;
margin: 10px 0 0 10px;
display: inline-block;
}
* #playerControler .vPlayVolumeWrap #vPlayVolume #dragBar,
html #playerControler .vPlayVolumeWrap #vPlayVolume #dragBar,
body #playerControler .vPlayVolumeWrap #vPlayVolume #dragBar,
video #playerControler .vPlayVolumeWrap #vPlayVolume #dragBar {
width: 8px;
height: 8px;
border-radius: 4px;
background: #369;
position: absolute;
top: -3px;
left: 0;
cursor: pointer;
}
* #playerControler .vPlayVolumeWrap #vPlayVolume #dragMask,
html #playerControler .vPlayVolumeWrap #vPlayVolume #dragMask,
body #playerControler .vPlayVolumeWrap #vPlayVolume #dragMask,
video #playerControler .vPlayVolumeWrap #vPlayVolume #dragMask {
position: absolute;
left: 0;
top: 0;
background: #369;
width: 0;
height: 2px;
}
* #playerControler #fullScreen,
html #playerControler #fullScreen,
body #playerControler #fullScreen,
video #playerControler #fullScreen {
width: 24px;
height: 24px;
float: right;
margin: 5px 2% 0 0;
display: block;
background: url(“data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAA/UlEQVRIS91V2w3CMAy8qP0HNoAJoOrtQ9mgI8AEiAlgBAZxJEaADWCBGqUqUktbkSAVAfmMH+ezk7PBwMcMnB+fB7DW5kVRLI0xixq7K8lJna2IXAGMandnVT3GcbxJksTZytNg4JKr6rajbTeS4xcAD/OOZN4JICInAHNjzCpN00PIfGrFnUnO+gDUGUi+NRsRacU3EnU5hLD4CoBy+s8D9WVRvaxG/Fu99gVsPdOQQF/fP2NQDUmfZcG3HV3x//cPBpeKUuwA5CR3vr13ftbaTFX3AC4kp6Fy7bMPXst1VYnbCVnF5BHksw8uAI5RFK17F05IS3x9f/8n3wFQDZcZDw/gGQAAAABJRU5ErkJggg==”) no-repeat center;
}
* #progressBar,
html #progressBar,
body #progressBar,
video #progressBar {
width: 100%;
background: #333;
height: 2px;
position: absolute;
bottom: 0;
display: block;
}
* #progressBar .reloadProgress,
html #progressBar .reloadProgress,
body #progressBar .reloadProgress,
video #progressBar .reloadProgress {
width: 0;
height: 2px;
background: #ccc;
position: relative;
left: 0;
top: 0;
z-index: 999;
}
* #progressBar .reloadProgress .progress,
html #progressBar .reloadProgress .progress,
body #progressBar .reloadProgress .progress,
video #progressBar .reloadProgress .progress {
width: 0;
height: 2px;
background: #008b8b;
position: absolute;
left: 0;
top: 0;
z-index: 9999;
}
* .fadeIn,
html .fadeIn,
body .fadeIn,
video .fadeIn {
animation-name: fadeIn;
}
* .fadeOut,
html .fadeOut,
body .fadeOut,
video .fadeOut {
animation-name: fadeOut;
}
@-moz-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@-webkit-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@-o-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@-moz-keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
@-webkit-keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
@-o-keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
@keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
video::-webkit-media-controls,
video::-moz-media-controls,
video::-webkit-media-controls-enclosure {
display: none !important;
}
video::-webkit-media-controls-panel,
video::-webkit-media-controls-panel-container,
video::-webkit-media-controls-start-playback-button {
display: none !important;
-webkit-appearance: none;
}[/cc]
4、html部分代码
[cc lang=”html”]
[/cc]
5、javascript部分代码
[cc lang=”javascript”]”use strict”
window.onload = function () {
var vPlayer = document.getElementById(‘vPlayer’)
var playerContent = document.getElementById(‘playerContent’)
var playerControl = document.getElementById(‘playerControler’)
var play = document.getElementById(‘play’)
var pause = document.getElementById(‘pause’)
var reloadProgressDOM = document.getElementById(‘progressBar’)
var progressTimeShowDOM = document.getElementById(‘vplayerTimeLine’)
var volumeIconDOM = document.getElementById(‘volumeIcon’)
var vPlayVolumeDOM = document.getElementById(‘vPlayVolume’)
var dragBarDOM = document.getElementById(‘dragBar’)
var dragMaskDOM = document.getElementById(‘dragMask’)
var fullscreen = document.getElementById(‘fullScreen’)
var _playerControlHidden,_playTime
var isSupportTouch = ‘ontouchend’ in document ? true : false;
// console.log(‘isSupportTouc’,isSupportTouch)
playerContent.controls = false
playerContent.preload = ‘auto’
//3000ms hidden player
playerControlHidden()
//play
play.onclick = function () {
vPlayerPlay()
}
// play.ontouchstart = function () {
// vPlayerPlay()
// }
//pause
pause.onclick = function () {
vPlayerPause()
}
// pause.ontouchstart = function () {
// vPlayerPause()
// }
//show player control
if(!isSupportTouch){
playerContent.addEventListener(‘mouseover’,playerControlShow)
}else{
playerContent.addEventListener(‘touchstart’,playerControlShow)
}
//hidden player control
if(!isSupportTouch){
playerContent.addEventListener(‘mouseleave’,playerControlHidden)
}else{
playerContent.addEventListener(‘touchend’,playerControlHidden)
}
function vPlayerPlay() {
progressBar()
playerContent.play()
play.style.display = ‘none’;
pause.style.display = ‘block’;
}
function vPlayerPause() {
if(_playTime){
clearInterval(_playTime)
}
playerContent.pause()
pause.style.display = ‘none’;
play.style.display = ‘block’;
}
function playerControlShow() {
// console.log(‘start’)
if(_playerControlHidden){
clearTimeout(_playerControlHidden)
}
if(!playerControl.style.opacity) return
playerControl.style.display = ‘block’
playerControl.style.animation = ‘fadeIn 1s’
playerControl.style.opacity = 1
}
function playerControlHidden() {
// console.log(‘hidden’)
_playerControlHidden = setTimeout(function () {
playerControl.style.animation = ‘fadeOut 1s’
playerControl.style.opacity = 0
playerControl.style.display = ‘none’
},3000)
}
function progressBar() {
_playTime = setInterval(function () {
// console.log(playerContent.buffered.end(0))
//reload progress time (加载的时间/总时间)*100 = 加载的百分比
var reloadProgressTime = (playerContent.buffered.end(0) / playerContent.duration) * 100
reloadProgressDOM.children[0].style.width = reloadProgressTime + ‘%’
//progress time = (playerContent.currentTime/playerContent.duration)*100
var progressTime = playerContent.currentTime
reloadProgressDOM.children[0].children[0].style.width = (progressTime / playerContent.duration) * 100 + ‘%’
//progress time show
progressTimeShowDOM.innerText = secToTime(progressTime)+’ | ‘+secToTime(playerContent.duration)
// console.log(playerContent.duration,playerContent.currentTime,playerContent.buffered.end(0))
if(playerContent.currentTime === playerContent.duration){
clearInterval(_playTime)
vPlayerPause()
reloadProgressDOM.children[0].children[0].style.width = 0
}
},1)
}
//volume drag control
playerContent.volume = 0.5
dragMaskDOM.style.width = ‘50%’
dragBarDOM.style.left = ‘50%’
if(!isSupportTouch) {
dragBarDOM.onmousedown = function (event) {
drag(event, this)
}
}else {
dragBarDOM.ontouchstart = function (event) {
console.log(event)
drag(event, this)
}
}
/**
* drag element
* @param event event
* @param ele element
*/
function drag(event,ele) {
var event = event || window.event;
var lengthX
if(!isSupportTouch){
lengthX = event.clientX – ele.offsetLeft;
}else {
lengthX = event.touches[0].clientX – ele.offsetLeft;
}
if(!isSupportTouch) {
document.onmousemove = function (event) {
dragMove(event,ele,lengthX)
}
}else{
document.ontouchmove = function (event) {
dragMove(event,ele,lengthX)
}
}
}
/**
* drag move volume: volume+ volume-
* @param event event
* @param ele element
* @param x lengthX:clientX
*/
function dragMove(event,ele,x) {
var event = event || window.event;
var barleft
if(!isSupportTouch) {
barleft = event.clientX – x;
}else {
barleft = event.touches[0].clientX – x;
}
if(barleft < 0)
barleft = 0;
else if(barleft > vPlayVolumeDOM.offsetWidth – dragBarDOM.offsetWidth)
barleft = vPlayVolumeDOM.offsetWidth – dragBarDOM.offsetWidth;
dragMaskDOM.style.width = barleft +’px’ ;
ele.style.left = barleft + ‘px’;
var volumeValue = barleft/(vPlayVolumeDOM.offsetWidth-dragBarDOM.offsetWidth)
// console.log(volumeValue)
playerContent.volume = parseFloat(volumeValue)
//防止选择内容–当拖动鼠标过快时候,弹起鼠标,bar也会移动,修复bug
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
}
document.onmouseup = function(){
document.onmousemove = null; //移除事件
}
document.ontouchend = function () {
document.ontouchstart = null
document.ontouchmove = null
}
volumeIconDOM.onclick = function () {
if(playerContent.volume != 0){
playerContent.volume = 0
dragMaskDOM.style.width = ‘0’
dragBarDOM.style.left = ‘0’
}else{
playerContent.volume = 0.5
dragMaskDOM.style.width = ‘50%’
dragBarDOM.style.left = ‘50%’
}
}
//video fullscreen
fullscreen.onclick = function () {
if(playerContent.webkitRequestFullScreen){
playerContent.webkitRequestFullScreen()
}else if(playerContent.mozRequestFullScreen){
playerContent.mozRequestFullScreen()
}else {
playerContent.requestFullscreen()
}
}
console.log(‘networkState’,playerContent.networkState)
/**
* format second to hh:mm:ss
* @param second second
* @returns {*} format time to 00:00:00
*/
var secToTime = function (second) {
var t
if(second > -1){
var hour = Math.floor(second/3600)
var min = Math.floor(second/60) % 60
var sec = second % 60
if(hour < 10) {
t = '0'+ hour + ":"
} else {
t = hour + ":"
}
if(min < 10){t += "0"}
t += min + ":"
if(sec < 10){t += "0"}
t += sec.toFixed(0)
}
return t
}
}[/cc]
整个项目很简单,希望能够帮助到准备进入video事件以及视频处理的同学,此项目已经上传到github,如果你喜欢,请记得给我加星哦!
github:https://github.com/king2088/html5-vPlayer