个性化html5中的video,打造属于自己的html5视频播放器

本文使用的都是CSS3以及html5中的video实现的播放器,在PC与手机端都可以完美播放,目前还未实现播放进度条的拖移功能,后续会增加这个功能。
demo效果查看地址:https://king2088.github.io/html5-vPlayer/
先看效果图:

html5 video
html5 video

首先我们要了解一下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

[ "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" ]

3、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;
}

4、html部分代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
    <title>vPlayer</title>
    <link rel="stylesheet" href="css/style.css">

</head>
<body>
    <div id="vPlayer">
        <video id="playerContent">
            <!--<source src="http://media.w3.org/2010/05/sintel/trailer.webm" type='video/webm;codecs="vp8, vorbis"'/>-->
            <source src="http://media.w3.org/2010/05/bunny/movie.mp4" type='video/mp4;codecs="avc1.42E01E, mp4a.40.2"'/>
        </video>
        <div id="playerControler">
            <div class="playButtonWrap">
                <div id="play" class="playButton"></div>
                <div id="pause" class="pauseButton"></div>
            </div>
            <div id="vplayerTimeLine"></div>
            <div id="fullScreen"></div>
            <div class="vPlayVolumeWrap">
                <div id="volumeIcon"></div>
                <div id="vPlayVolume">
                    <div id="dragBar"></div>
                    <div id="dragMask"></div>
                </div>
            </div>

        </div>
        <div id="progressBar">
            <div class="reloadProgress">
                <div class="progress"></div>
            </div>
        </div>
    </div>
    <script src="js/man.js"></script>
</body>
</html>

5、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
    }
}

整个项目很简单,希望能够帮助到准备进入video事件以及视频处理的同学,此项目已经上传到github,如果你喜欢,请记得给我加星哦!
github:https://github.com/king2088/html5-vPlayer

发表评论

电子邮件地址不会被公开。 必填项已用*标注