小强的HTML5移动开发之路(5)——制作一个漂亮的视频播放器
在前面几篇文章中介绍了HTML5的特点和需要掌握的基础知识,下面我们开始真正的体验一下Html5的优势,我们开始制作一个漂亮的视频播放器吧先别急,在开始制作之前先了解一下视频文件的基本知识。
一、视频的格式
目前比较主流和使用比较的的视频格式主要有:avi、rmvb、wmv、mpeg4、ogg、webm。这些视频都是由视频、音频、编码格式三部分组成的。在HTML5中,根据浏览器的不同,目前拥有多套不同的编码器:
H.264(个人不看好):这个编码器是苹果系统包括苹果手机中的编码器,拥有专利的视频编码器。在编码及传输过程中的任何部分都可能需要收取专利费。因此Safari(苹果的浏览器)和Intenet Explorer支持该编码器,但是在开源已经成为大势的当下,还在浏览器中收取专利费,个人实在是不看好啊。
Theora:这是一个不受专利限制的编码格式,并且对所有等级的编码、传输以及回放免费的视频编码器。Chrome、Firefox以及Opera支持该编码器。
VP8:该视频编码器与Theora相似,但是其拥有者是Google公司,Google公司已经开源,因此不需要专利费。Chrome、Firefox以及Opera支持该编码器。
AAC:音频编码器,与H.264相同,该音频编码器拥有专利限制,Safari、Chrome和Internet Explorer支持该音频编码器。
MP3:也是一个专利技术,Safari、Chrome和Internet Explorer支持该音频编码器。
PCM:存储由模拟数字转换器编码的完整数据,在音频CD上存储数据的一种格式。是以中国无损编码器,它的文件大小一般是AAC和MP3文件的几倍,Safari、Firefox和Internet Explorer支持该音频编码器。
Vorbis:文件扩展名为.ogg,有时候也被称为Ogg Vorbis,该音频编码器不受专利保护,因此版权免费。支持的浏览器包括Chrome、Firefox和Opera.
主流浏览器和设备支持的视频和音频
二、HTML5中的<vido>属性
在html5中可以使用<audio>或者<video>标签播放html5媒体,使用方式如下
<video src="move.mp4"></video>
video标签中有很多属性,例如controls属性可以控制是否有控制台。
<video src="move.mp4" controls="controls"> 浏览器不支持HTML5的视频播放功能 </video>
从上面的视频格式中我们可以看到不同的浏览器支持不同的视频格式,这样我们可以采用<source>标签指定多种格式的视频,默认情况下浏览器会自动启动下载文件来确定其类型。
<video width="400" controls="controls"> <source src="move.mp4" type="video/mp4" /> <source src="move.ogg" type="video/ogg" /> </video>
三、制作视频播放器
index.html
<!DOCTYPE html> <html> <head> <title>Demo 1 | Custom HTML5 Video Controls with jQuery</title> <link rel="stylesheet" href="../vendorstyle.css" /> <link rel="stylesheet" href="style.css" /> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <!--[if lt IE 9]> <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <script src="../vendorscript.js"></script> <script src="video.js"></script> <!--[if lt IE 9]> <script> $(document).ready(function() { $('.control').hide(); $('.loading').fadeOut(500); $('.caption').fadeOut(500); }); </script> <![endif]--> <link rel="shortcut icon" href="http://www.inwebson.com/wp-content/themes/inwebson/favicon.ico" /> </head> <body> <!-- Header --> <header> <h1>Custom HTML5 Video Controls with jQuery</h1> <p id="backlinks"> <a href="http://www.inwebson.com/custom-html5-video-controls-with-jquery-and-css/">BACK TO ARTICLE »</a> <a href="http://www.inwebson.com">Visit inWebson.com »</a> </p> <p class="clearfix"></p> </header> <!-- Content --> <section id="wrapper"> <!-- Title --> <h2>Demo 1</h2> <h3>Custom HTML5 Video Controls</h3> <p class="videoContainer"> <video id="myVideo" controls preload="auto" poster="poster.jpg" width="600" height="350" > <source src="http://demo.inwebson.com/html5-video/iceage4.mp4" type="video/mp4" /> <source src="http://demo.inwebson.com/html5-video/iceage4.webm" type="video/webM" /> <source src="http://demo.inwebson.com/html5-video/iceage4.ogv" type="video/ogg" /> <p>Your browser does not support the video tag.</p> </video> <p class="caption">This is HTML5 video with custom controls</p> <p class="control"> <p class="topControl"> <p class="progress"> <span class="bufferBar"></span> <span class="timeBar"></span> </p> <p class="time"> <span class="current"></span> / <span class="duration"></span> </p> </p> <p class="btmControl"> <p class="btnPlay btn" title="Play/Pause video"></p> <p class="btnStop btn" title="Stop video"></p> <p class="spdText btn">Speed: </p> <p class="btnx1 btn text selected" title="Normal speed">x1</p> <p class="btnx3 btn text" title="Fast forward x3">x3</p> <p class="btnFS btn" title="Switch to full screen"></p> <p class="btnLight lighton btn" title="Turn on/off light"></p> <p class="volume" title="Set volume"> <span class="volumeBar"></span> </p> <p class="sound sound2 btn" title="Mute/Unmute sound"></p> </p> </p> <p class="loading"></p> </p> <!-- Navigation --> <nav id="navigation"> <ul> <li class="currentbtn"><a href="#" title="Demo 1">DEMO 1</a></li> <li><a href="../demo2/" title="Demo 2">DEMO 2</a></li> </ul> <p class="clearfix"></p> </nav> </section> <!-- Footer --> <footer> <span>© 2011 <a href="http://www.inwebson.com">inWebson.com</a>. Design by <a href="http://www.inwebson.com/contactus">Kenny Ooi</a>. Powered by <a href="http://www.inwebson.com/html5/">HTML5</a> and <a href="http://www.inwebson.com/jquery/">jQuery</a>.</span> </footer> </body> </html>
style.css
/* video container */ .videoContainer{ width:600px; height:350px; position:relative; overflow:hidden; background:#000; color:#ccc; } /* video caption css */ .caption{ display:none; position:absolute; top:0; left:0; width:100%; padding:10px; color:#ccc; font-size:20px; font-weight:bold; box-sizing: border-box; -ms-box-sizing: border-box; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; background: #1F1F1F; /* fallback */ background:-moz-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%); background:-webkit-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%); background:-o-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%); } /*** VIDEO CONTROLS CSS ***/ /* control holder */ .control{ background:#333; color:#ccc; position:absolute; bottom:0; left:0; width:100%; z-index:5; display:none; } /* control top part */ .topControl{ height:11px; border-bottom:1px solid #404040; padding:1px 5px; background:#1F1F1F; /* fallback */ background:-moz-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%); background:-webkit-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%); background:-o-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%); } /* control bottom part */ .btmControl{ clear:both; background: #1F1F1F; /* fallback */ background:-moz-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%); background:-webkit-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%); background:-o-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%); } .control p.btn { float:left; width:34px; height:30px; padding:0 5px; border-right:1px solid #404040; cursor:pointer; } .control p.text{ font-size:12px; font-weight:bold; line-height:30px; text-align:center; font-family:verdana; width:20px; border:none; color:#777; } .control p.btnPlay{ background:url(control.png) no-repeat 0 0; border-left:1px solid #404040; } .control p.paused{ background:url(control.png) no-repeat 0 -30px; } .control p.btnStop{ background:url(control.png) no-repeat 0 -60px; } .control p.spdText{ border:none; font-size:14px; line-height:30px; font-style:italic; } .control p.selected{ font-size:15px; color:#ccc; } .control p.sound{ background:url(control.png) no-repeat -88px -30px; border:none; float:right; } .control p.sound2{ background:url(control.png) no-repeat -88px -60px !important; } .control p.muted{ background:url(control.png) no-repeat -88px 0 !important; } .control p.btnFS{ background:url(control.png) no-repeat -44px 0; float:right; } .control p.btnLight{ background:url(control.png) no-repeat -44px -60px; border-left:1px solid #404040; float:right; } .control p.lighton{ background:url(control.png) no-repeat -44px -30px !important; } /* PROGRESS BAR CSS */ /* Progress bar */ .progress { width:85%; height:10px; position:relative; float:left; cursor:pointer; background: #444; /* 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:10px; -moz-border-radius:10px; -webkit-border-radius:10px; } .progress span { height:100%; position:absolute; top:0; left:0; display:block; border-radius:10px; -moz-border-radius:10px; -webkit-border-radius:10px; } .timeBar{ z-index:10; width:0; background: #3FB7FC; /* 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 */ .time{ width:15%; float:right; text-align:center; font-size:11px; line-height:12px; } /* VOLUME BAR CSS */ /* volume bar */ .volume{ position:relative; cursor:pointer; width:70px; height:10px; float:right; margin-top:10px; margin-right:10px; } .volumeBar{ display:block; height:100%; position:absolute; top:0; left:0; background-color:#eee; z-index:10; } /* OTHERS CSS */ /* video screen cover */ .loading, #init{ position:absolute; top:0; left:0; width:100%; height:100%; background:url(loading.gif) no-repeat 50% 50%; z-index:2; display:none; } #init{ background:url(bigplay.png) no-repeat 50% 50% !important; cursor:pointer; }
video.js
$(document).ready(function(){ //INITIALIZE var video = $('#myVideo'); //remove default control when JS loaded video[0].removeAttribute("controls"); $('.control').show().css({'bottom':-45}); $('.loading').fadeIn(500); $('.caption').fadeIn(500); //before everything get started video.on('loadedmetadata', function() { $('.caption').animate({'top':-45},300); //set video properties $('.current').text(timeFormat(0)); $('.duration').text(timeFormat(video[0].duration)); updateVolume(0, 0.7); //start to get video buffering data setTimeout(startBuffer, 150); //bind video events $('.videoContainer') .append('<p id="init"></p>') .hover(function() { $('.control').stop().animate({'bottom':0}, 500); $('.caption').stop().animate({'top':0}, 500); }, function() { if(!volumeDrag && !timeDrag){ $('.control').stop().animate({'bottom':-45}, 500); $('.caption').stop().animate({'top':-45}, 500); } }) .on('click', function() { $('#init').remove(); $('.btnPlay').addClass('paused'); $(this).unbind('click'); video[0].play(); }); $('#init').fadeIn(200); }); //display video buffering bar var startBuffer = function() { var currentBuffer = video[0].buffered.end(0); var maxduration = video[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[0].currentTime; var maxduration = video[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[0].paused || video[0].ended) { $('.btnPlay').addClass('paused'); video[0].play(); } else { $('.btnPlay').removeClass('paused'); video[0].pause(); } }; //speed text clicked $('.btnx1').on('click', function() { fastfowrd(this, 1); }); $('.btnx3').on('click', function() { fastfowrd(this, 3); }); var fastfowrd = function(obj, spd) { $('.text').removeClass('selected'); $(obj).addClass('selected'); video[0].playbackRate = spd; video[0].play(); }; //stop button clicked $('.btnStop').on('click', function() { $('.btnPlay').removeClass('paused'); updatebar($('.progress').offset().left); video[0].pause(); }); //fullscreen button clicked $('.btnFS').on('click', function() { if($.isFunction(video[0].webkitEnterFullscreen)) { video[0].webkitEnterFullscreen(); } else if ($.isFunction(video[0].mozRequestFullScreen)) { video[0].mozRequestFullScreen(); } else { alert('Your browsers doesn\'t support fullscreen'); } }); //light bulb button clicked $('.btnLight').click(function() { $(this).toggleClass('lighton'); //if lightoff, create an overlay if(!$(this).hasClass('lighton')) { $('body').append('<p class="overlay"></p>'); $('.overlay').css({ 'position':'absolute', 'width':100+'%', 'height':$(document).height(), 'background':'#000', 'opacity':0.9, 'top':0, 'left':0, 'z-index':999 }); $('.videoContainer').css({ 'z-index':1000 }); } //if lighton, remove overlay else { $('.overlay').remove(); } }); //sound button clicked $('.sound').click(function() { video[0].muted = !video[0].muted; $(this).toggleClass('muted'); if(video[0].muted) { $('.volumeBar').css('width',0); } else{ $('.volumeBar').css('width', video[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[0].pause(); }); //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[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[0].currentTime = maxduration * percentage / 100; }; //VOLUME BAR //volume bar event var volumeDrag = false; $('.volume').on('mousedown', function(e) { volumeDrag = true; video[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[0].volume = percentage / 100; //change sound icon based on volume if(video[0].volume == 0){ $('.sound').removeClass('sound2').addClass('muted'); } else if(video[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 ? "0"+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; }; });
以上就是 小强的HTML5移动开发之路(5)——制作一个漂亮的视频播放器的内容,更多相关内容请关注PHP中文网(www.php.cn)!
- 小强的HTML5移动开发之路(4)——CSS2和CSS3
- 小强的HTML5移动开发之路(6)——Canvas图形绘制基础