使用自定义控件制作HTML5视频/音频播放列表播放器

making an html5 video/audio playlist player with custom controls

本文关键字:音频 播放列表 播放器 视频 HTML5 自定义控件      更新时间:2023-09-26

我正在制作一个带有自定义控件的HTML5视频/音频播放列表播放器。

我有适用于单个视频的自定义控件,但我无法将这些控件和当前时间/持续时间属性绑定到用户可能单击的每个视频上。

这里有一个jsfiddle,说明了我的意思。

代码也在这个问题的底部。请不要害怕,JS的底部90%是自定义控件。前 10% 是定义视频对象和on单击功能以选择所需的视频。

我已将默认值设置为播放"视频 2"(共 3 个)。自定义控件控制"视频 2"。这些按钮切换每个视频的播放/暂停,但您会注意到,无论单击哪个按钮,自定义控件仍控制"视频 2"。

基本上,我只需要找到一种方法,当您单击每个视频按钮时,所有控件和属性(当前时间,持续时间)都会绑定到所选视频。

.HTML:

<button class="icon" data-id="1" >Video 1</button>
<button class="icon" data-id="2">Video 2</button>
<button class="icon" data-id="3">Video 3</button>
<div id="url"  data-id="2"></div>
<div class="videoContainer">  
<video data-id="1" width="100%" height="80%"    poster="http://www.birds.com/wp-content/uploads/home/bird.jpg" >    
<source src="http://video-js.zencoder.com/oceans-clip.mp4" type="video/mp4" />
</video>
<video data-id="2"  width="100%" height="80%"  poster="http://www.logobird.com/wp-content/uploads/2011/03/new-google-chrome-logo.jpg">
<source src="http://www.html5rocks.com/en/tutorials/video/basics/Chrome_ImF.mp4" type="video/mp4" />
</video>
<video data-id="3" width="100%" height="80%"  poster="http://cheerioscoupons.info/wp-content/uploads/_Cheerios-Coupons-1-300x283.jpg">
<source src="http://media.jilion.com/videos/demo/midnight_sun_sv1_360p.mp4" type="video/mp4" />
</video>
    <div class="progress">
        <span class="bufferBar"></span>
        <span class="timeBar"></span>
    </div>
    <div class="control">    
        <div class="btnPlay btn btn-primary" title="Play/Pause video">PLAY</div>        
        <div class="time">
            <span class="current"></span> / 
            <span class="duration"></span> 
        </div>    
        <div class="sound sound2 btn btn-primary" title="Mute/Unmute sound"></div>
        <div class="volume" title="Set volume">VOLUME
            <span class="volumeBar"></span>
        </div>
        <div class="btnFS btn btn-primary" title="Switch to full screen">FULLSCREEN</div>
    </div><!--/control-->   
</div><!--/videocontainer-->​ 

.JS:

var url=$('#url').data('id');
var $video=$('video[data-id="'+url+'"]');
$('video').not($('video[data-id="'+url+'"]')).hide();

$('.icon').click(function(){
var id=$(this).data('id'),
    $video=$("video[data-id='" + id +"']");
$('video').each(function () {
    this.pause();
    //this.currentTime = 0;
});
   $('video').not($video).hide();
   $video.show();    
   $video.get(0).play();   
});    

//before everything get started
$video.on('loadedmetadata', function() {
        //set video properties
        $('.current').text(timeFormat(0));
        $('.duration').text(timeFormat($video.get(0).duration));
        updateVolume(0, 0.7);
        //start to get video buffering data 
        setTimeout(startBuffer, 150);
        //bind video events
        $('.videoContainer').on('click', function() {
            $('.btnPlay').find('i').addClass('icon-pause');
            $(this).unbind('click');
            $video.get(0).play();
        });
    });
    //display video buffering bar
    var startBuffer = function() {
        var currentBuffer = $video.get(0).buffered.end(0);
        var maxduration = $video.get(0).duration;
        var perc = 100 * currentBuffer / maxduration;
        $('.bufferBar').css('width',perc+'%');
        if(currentBuffer < maxduration) {
            setTimeout(startBuffer, 500);
        }
    };    
    //display current video play time
    $video.on('timeupdate', function() {
        var currentPos = $video.get(0).currentTime;
        var maxduration = $video.get(0).duration;
        var perc = 100 * currentPos / maxduration;
        $('.timeBar').css('width',perc+'%');    
        $('.current').text(timeFormat(currentPos));    
    });
    //CONTROLS EVENTS
    //video screen and play button clicked
    $video.on('click', function() { playpause(); } );
    $('.btnPlay').on('click', function() { playpause(); } );
    var playpause = function() {
        if($video.get(0).paused || $video.get(0).ended) {
            $('.btnPlay').find('i').addClass('icon-pause');
            $video.get(0).play();
        }
        else {
            $('.btnPlay').find('i').removeClass('icon-pause');
            $video.get(0).pause();
        }
    };
    //fullscreen button clicked
    $('.btnFS').on('click', function() {
        if($.isFunction($video.get(0).webkitEnterFullscreen)) {
            $video.get(0).webkitEnterFullscreen();
        }    
        else if ($.isFunction($video.get(0).mozRequestFullScreen)) {
            $video.get(0).mozRequestFullScreen();
        }
        else {
            alert('Your browsers doesn''t support fullscreen');
        }
    });
    //sound button clicked
    $('.sound').click(function() {
        $video.get(0).muted = !$video.get(0).muted;
        $(this).toggleClass('muted');
        if($video.get(0).muted) {
            $('.volumeBar').css('width',0);
        }
        else{
            $('.volumeBar').css('width', $video.get(0).volume*100+'%');
        }
    });
    //VIDEO EVENTS
    //video canplay event
    $video.on('canplay', function() {
        $('.loading').fadeOut(100);
    });
    //video canplaythrough event
    //solve Chrome cache issue
    var completeloaded = false;
    $video.on('canplaythrough', function() {
        completeloaded = true;
    });
    //video ended event
    $video.on('ended', function() {
        $('.btnPlay').removeClass('paused');
        $video.get(0).pause();
    });
    $video.on('ended', function() {
       var nextVideo= $(this).next();
        if(!$('video').last()){
          $(this).hide();
          nextVideo.show(); 
          nextVideo.get(0).play();  
        }        
    }); //onended

    //video seeking event
    $video.on('seeking', function() {
        //if video fully loaded, ignore loading screen
        if(!completeloaded) { 
        //    $('.loading').fadeIn(200);
        }    
    });
    //video seeked event
    $video.on('seeked', function() { });
    //video waiting for more data event
    $video.on('waiting', function() {
        $('.loading').fadeIn(200);
    });
    //VIDEO PROGRESS BAR
    //when video timebar clicked
    var timeDrag = false;    /* check for drag event */
    $('.progress').on('mousedown', function(e) {
        timeDrag = true;
        updatebar(e.pageX);
    });
    $(document).on('mouseup', function(e) {
        if(timeDrag) {
            timeDrag = false;
            updatebar(e.pageX);
        }
    });
    $(document).on('mousemove', function(e) {
        if(timeDrag) {
            updatebar(e.pageX);
        }
    });
    var updatebar = function(x) {
        var progress = $('.progress');
        //calculate drag position
        //and update video currenttime
        //as well as progress bar
        var maxduration = $video.get(0).duration;
        var position = x - progress.offset().left;
        var percentage = 100 * position / progress.width();
        if(percentage > 100) {
            percentage = 100;
        }
        if(percentage < 0) {
            percentage = 0;
        }
        $('.timeBar').css('width',percentage+'%');    
        $video.get(0).currentTime = maxduration * percentage / 100;
    };
    //VOLUME BAR
    //volume bar event
    var volumeDrag = false;
    $('.volume').on('mousedown', function(e) {
        volumeDrag = true;
        $video.get(0).muted = false;
        $('.sound').removeClass('muted');
        updateVolume(e.pageX);
    });
    $(document).on('mouseup', function(e) {
        if(volumeDrag) {
            volumeDrag = false;
            updateVolume(e.pageX);
        }
    });
    $(document).on('mousemove', function(e) {
        if(volumeDrag) {
            updateVolume(e.pageX);
        }
    });
    var updateVolume = function(x, vol) {
        var volume = $('.volume');
        var percentage;
        //if only volume have specificed
        //then direct update volume
        if(vol) {
            percentage = vol * 100;
        }
        else {
            var position = x - volume.offset().left;
            percentage = 100 * position / volume.width();
        }
        if(percentage > 100) {
            percentage = 100;
        }
        if(percentage < 0) {
            percentage = 0;
        }
        //update volume bar and video volume
        $('.volumeBar').css('width',percentage+'%');    
        $video.get(0).volume = percentage / 100;
        //change sound icon based on volume
        if($video.get(0).volume == 0){
            $('.sound').removeClass('sound2').addClass('muted');
        }
        else if($video.get(0).volume > 0.5){
            $('.sound').removeClass('muted').addClass('sound2');
        }
        else{
            $('.sound').removeClass('muted').removeClass('sound2');
        }
    };
    //Time format converter - 00:00
    var timeFormat = function(seconds){
        var m = Math.floor(seconds/60)<10 ? Math.floor(seconds/60) : Math.floor(seconds/60);
        var s = Math.floor(seconds-(m*60))<10 ? "0"+Math.floor(seconds-(m*60)) : Math.floor(seconds-(m*60));
        return m+":"+s;
    };

.CSS:

 /* video container */
.videoContainer{
width:97.8%;
height:250px;
overflow:hidden;
background:#ccc;
color:#ccc;
}
 /*** VIDEO CONTROLS CSS ***/
/* control holder */
.control{
background:#333;
color:#ccc;
width:100%;
z-index:5;   
}
.control >div{
display:inline-block;
}
.control div.btn { 
cursor:pointer;
}
.control div.text{
font-size:18px;
line-height:30px;
text-align:center;
width:20px;
}
.control div.selected{
font-size:18px;
color:#ccc;
}
.control div.sound{
background:url(/assets/img/video/control.png) no-repeat -88px -30px;
border:none;
}
.control div.sound2{
background:url(/assets/img/video/control.png) no-repeat -88px -60px !important;
}
.control div.muted{
background:url(/assets/img/video/control.png) no-repeat -88px 0 !important;
}
.control div.btnFS{
float:right;
}
/* PROGRESS BAR CSS */
/* Progress bar */
.progress {
width:100%;
height:24px;   
position:relative;
float:left;
cursor:pointer;
background: gray; /* fallback */
background:-moz-linear-gradient(top,#666,#333);
background:-webkit-linear-gradient(top,#666,#333);
background:-o-linear-gradient(top,#666,#333);
box-shadow:0 2px 3px #333 inset;
-moz-box-shadow:0 2px 3px #333 inset;
-webkit-box-shadow:0 2px 3px #333 inset;
border-radius:5px;
-moz-border-radius:5px;
-webkit-border-radius:5px;
}
.progress span { 
height:100%;
position:relative;
top:0;
left:0;
display:inline-block;
height:100%;
position:absolute;
top:0;
left:0;
display:block;
border-radius:5px;
-moz-border-radius:5px;
-webkit-border-radius:5px;
}
.timeBar{
position:absolute;
left:0px;
top:0px;
z-index:10;
width:0;
background: #006DCC; /* fallback */
background:-moz-linear-gradient(top,#A0DCFF 50%,#3FB7FC 50%,#16A9FF 100%);
background:-webkit-linear-gradient(top,#A0DCFF 50%,#3FB7FC 50%,#16A9FF 100%);
background:-o-linear-gradient(top,#A0DCFF 50%,#3FB7FC 50%,#16A9FF 100%);
box-shadow:0 0 1px #fff;
-moz-box-shadow:0 0 1px #fff;
-webkit-box-shadow:0 0 1px #fff;
}
.bufferBar{
z-index:5;
width:0;
background: #777;
background:-moz-linear-gradient(top,#999,#666);
background:-webkit-linear-gradient(top,#999,#666);
background:-o-linear-gradient(top,#999,#666);
box-shadow:2px 0 5px #333;
-moz-box-shadow:2px 0 5px #333;
-webkit-box-shadow:2px 0 5px #333;
}
/* time and duration */
/* VOLUME BAR CSS */
/* volume bar */
.volume{
position:relative;
cursor:pointer;
width:100px;
height:24px;

}
.volumeBar{
display:block;
height:100%;
position:absolute;
top:0;
left:0;
background-color:#006DCC;
z-index:10;
border-radius:5px;
-moz-border-radius:5px;
-webkit-border-radius:5px;
}
/* OTHERS CSS */
/* video screen cover */
.loading, #init{
width:100%;
height:100%;
z-index:2;
}
#init{
cursor:pointer;
}​

试试这个

我已经在图标单击上添加了此类

 $("video[data-id='" + id +"']").addClass("active");
 $video = $('video.active'); 

因此,这里尝试根据活动类选择视频,它工作正常。 当单击另一个视频时,请删除以前的活动类并将其添加到新选择的视频中。