- 構建移動網站與APP:HTML 5移動開發入門與實戰(跨平臺移動開發叢書)
- 常新峰
- 3586字
- 2020-11-29 00:14:07
3.3 范例——制作視頻播放器APP
上面的示例已經向讀者展示HTML 5帶來的video元素在瀏覽器視頻上的突破,擺脫了傳統瀏覽器播放視頻過度依賴于第三方插件的局面。雖然video非常美好,但是各種瀏覽器對視頻控件的實現不同,在原有的面板增加自定義功能更是難上加難。本例將初步實現一個自定義的播放器,給各位讀者提供一個思路。
本例播放器將實現3個基本功能:播放、暫停、全屏。使用Chrome瀏覽器打開網頁文件,運行結果如圖3.5所示。點擊視頻中央的播放按鈕,運行結果如圖3.6所示。

圖3.5 使用Chrome打開網頁文件

圖3.6 點擊視頻中央的播放按鈕
此時,中央的播放按鈕被隱藏,緊隨著出現視頻底部工具條。該工具條并非瀏覽器原生視頻工具條,而是通過HTML進行模擬定制。如圖3.6所示,工具條上出現了左下角暫停按鈕和右下角全屏按鈕。
提示
除了例子實現的3個功能外,后續例子將會在本例實現的基礎上進行加強,讀者可以繼續閱讀后續示例,感受自定義的魅力。
3.3.1 普通視頻播放器
利用編輯器打開“3-4.普通視頻播放器.html”文件,代碼如下:
【代碼3-4】
01 <! DOCTYPE HTML> 02 <html> 03 <head> 04 <style>/* ......此處樣式忽略,讀者可以查看對應源代碼 */</style> 05 <script src="../js/jquery-1.8.3.js"></script> 06 </head> 07 <body> 08 <header><h2>做一個自己的視頻播放器</h2></header> 09 <div class="video_box"> 10 <video src="../res/BigBuck.webm" width="480" height="320" controls></video> 11 </div> 12 </body> 13 <script> 14 (function () { 15 var CONTROLS_HTML = '......省略’; // 播放工具條HTML,此處省略 16 function VideoControl(ele) { // 播放工具條類 17 this.video = $(ele); 18 this.init(); 19 }; 20 VideoControl.prototype = { // 原型方法 21 init: function () { 22 // 移除video原本的controls屬性,去除瀏覽器默認工具條 23 this.video.removeAttr('controls'); 24 this._render(); 25 this._bind(); 26 }, 27 _render: function () { // 用于生成工具條html結構 28 var wraper = this.wraper = $(document.createElement('div')); 29 wraper.html(CONTROLS_HTML); 30 this.video.parent().append(wraper); // 將工具類插入文檔 31 }, 32 _bind: function () { // 給工具條的元素綁定事件 33 var self = this, 34 video = self.video.get(0), // 獲取對應的原生元素 35 wraper = self.wraper, 36 control_btn = wraper.find('div.control_btn'); 37 // 用jQuery的delegate方法委托特制元素監聽click事件 38 wraper.delegate('div[data-type]', 'click', function (e) { 39 var data_type = $(this).attr('data-type'); // 獲取按鈕自定義操作類型屬性 40 switch (data_type) { 41 case 'go': // 初始屏中間大按鈕 42 wraper.find('div.play_button').hide(); 43 wraper.find('div.play_controls').show(); 44 video.play(); // 播放視頻 45 break; 46 case 'play': // 自定義工具條播放鍵 47 control_btn.toggle(); 48 video.play(); 49 break; 50 case 'pause': // 自定義工具條暫停鍵 51 control_btn.toggle(); // 暫停視頻 52 video.pause(); 53 break; 54 case 'fullscreen': // 自定義工具條全屏鍵 55 self._fullScreen(video); // 調用實例的全屏方法 56 break; 57 }; 58 }); 59 }, 60 _fullScreen: function (video) { // 全屏方法 61 var prefixs = 'Webkit Moz O ms Khtml'.split(' '), // 各種瀏覽器全屏方法前綴 62 parent = video, prefix; 63 // 循環各瀏覽器前綴名,找尋符合的方法并執行 64 for (var i = 0, l = prefixs.length; i < l; i++) { 65 prefix = prefixs[i].toLowerCase(); 66 67 if (parent[prefix + 'EnterFullScreen']) { // 兼容不同瀏覽器全屏方法 68 parent[prefix + 'EnterFullScreen'](); 69 break; 70 } else if (parent[prefix + 'RequestFullScreen']) { 71 parent[prefix + 'RequestFullScreen'](); // 如果存在該方法即執行 72 break; 73 }; 74 }; 75 } 76 }; 77 new VideoControl(document.querySelector('video')); // 實例化自定義工具條類 78 })(); 79 </script> 80 </html>
代碼第16~19行定義了工具類構造函數。函數接收1個參數,該參數需要加入自定義工具條的video元素。
代碼第20~76行在VideoControl的prototype原型上增加如下4個方法:
● init:初始化函數。
● _render:生成工具條HTML結構。
● _bind:在工具條元素上綁定事件。
● _requestFullscreen:video元素全屏方法。
提示
prototype屬性是JavaScript面向對象編程的基礎,如果對其還不是很了解,可以參考http://msdn.microsoft.com/zh-cn/magazine/cc163419.aspx。
_render方法將字符模板CONTROLS_HTML插入對應的video父節點中,用于構建工具條DOM結構。
_bind方法在工具條的外圍容器增加事件委托,監聽元素類型為符合選擇器“div[datatype]”的click事件。data-type是自定義的元素屬性,表示播放按鈕的類型。本例中共有4種類型,具體如下:
● go:初始狀態中央的大三角按鈕事件類型。
● play:工具條播放按鈕事件類型。
● pause:工具條暫停按鈕事件類型。
● fullscreen:工具條全屏按鈕事件類型。
在各種瀏覽器上,video元素的播放和暫停方法的名稱都相同,分別為play和pause。全屏方法由于還處于草案階段,因此需要加上對應瀏覽器的前綴名,代碼第60~75行就是為了解決這個問題而設置的。兼容方案可以參考代碼,這里不做過多說明。
細心的讀者會發現,Chrome瀏覽器下調用video全屏方法后,不論video是否帶有controls屬性,都會出現播放器的默認工具條,這顯然不是當初想看到的,讀者不妨先想想,稍后會給出解決方案。
提示
本次代碼分析主要針對示例的腳本邏輯,樣式說明可以參考源碼中的注釋。
3.3.2 添加視頻進度條
本例將完成給自定義播放器添加進度條的工作。一共會添加兩種進度條,分別為下載進度條和播放進度條。使用Chrome瀏覽器打開網頁文件,點擊屏幕中央的三角播放按鈕,播放器底部出現自定義工具條,同時進度條慢慢地向右伸長,運行效果如圖3.7所示。

圖3.7 點擊播放按鈕
圖3.7中的藍色進度條表示播放時間,灰色條表示視頻下載進度。將鼠標懸浮于進度條之上,此時進度條上方會出現對應的時間提示框,效果如圖3.8所示。

圖3.8 鼠標懸浮于進度條出現時間提示
本例的代碼構建在“3-5.添加視頻進度條.html”的功能基礎之上。下面對增添的代碼部分做一個分析。
字符串模板CONTROLS_HTML增加進度條HTML結構,代碼如下:
'<div class="control progress_control">' + // 進度條外圍層 '<div class="progress_bar_bg"></div>' + // 進度條背景層 '<div class="progress_bar_buffered"></div>' + // 下載進度條層 '<div class="progress_bar_played"></div>' + // 播放進度條層 '<div class="progress_bar_time">' + // 懸浮提示外圍層 '<div class="progress_bar_time_line"></div>' + '<div class="progress_bar_time_txt">00:00</div>' + // 懸浮時間提示 '</div>' + '</div>' +
提示
HTML模板對應的CSS可以參考源碼。
視頻工具類VideoControl的prototype原型上增加_progress和_bartime方法。其中_progress方法用于控制下載進度條的移動,代碼如下:
_progress: function () { // 控制下載進度條 var self = this, video = self.video, // 實例上的video屬性 video_ele = video.get(0), // 視頻的原生元素 progress_bar = self.wraper.find('div.progress_control'), // 進度條外圍元素 progress_bar_buffered = self.wraper.find('div.progress_bar_buffered'); // 下載進度條元素 video.on({ 'progress': function (e) { // 監聽video的下載進度事件 if (this.buffered && this.buffered.length) { // 判斷是否開始接收數據 var percent = video_ele.buffered.end(0) / video_ele.duration; // 下載數據相對總時間百分比 progress_bar_buffered.width(percent * progress_bar.width()); // 設置下載進度條長度 }; } }); },
video的buffered屬性返回1個TimeRanges對象。TimeRanges對象表示音視頻的已緩沖部分,對象具有1個length屬性,表示音視頻中已緩沖范圍的數量,同時還具有兩個方法,即start和end,語法如下:
video. buffered.start(index); // 獲得某個已緩沖范圍的開始位置 video. buffered. end (index); // 獲得某個已緩沖范圍的結束位置
_bartime方法用于實現鼠標懸浮進度條的時間提示,代碼如下:
_bartime: function () { // 鼠標懸浮進度條的時間提示 var wraper = this.wraper, progress_control = wraper.find('div.progress_control'), // 進度條外圍元素 progress_bar_bg = wraper.find('div.progress_bar_bg'), // 進度條背景層 progress_bar_time = wraper.find('div.progress_bar_time'), // 時間懸浮提示層外框 progress_bar_time_txt = wraper.find('div.progress_bar_time_txt'), video_ele = this.video.get(0); // 懸浮提示時間元素 progress_bar_bg.on({ // 綁定進度條背景層 'mousemove': function (e) { var offsetX = e.clientX - progress_bar_bg.offset().left, // 相對于進度條橫軸距離 percent = offsetX / progress_bar_bg.width(); progress_bar_time.css('left', offsetX + 6); // 設置時間浮動框位置 progress_bar_time_txt.html(timeFormat((percent * video_ele.duration)|| 0)); }, 'mouseenter': function (){ progress_bar_time.show(); }, // 移入顯示時間提醒 'mouseleave': function (){ progress_bar_time.hide(); }// 移出隱藏時間提醒 }); }
最后,完成播放進度條的動態更新功能,修改原型方法_timeupdate,代碼如下:
this.video.on({ 'timeupdate': function () { // 視頻播放位置變動時觸發 currentTime.html(timeFormat(video.currentTime)); // 當前播放時間動態更新 var percent = video.currentTime / video.duration; // 播放時間占總時間百分比 progress_bar_played.width(percent * progress_bar.width()); // 設置播放進度條寬度 }, 'loadedmetadata': function () { // 視頻元數據加載完畢后觸發 duration.html(timeFormat(video.duration)); } });
在上面的代碼中,將之前監聽video的play事件換為loadedmetadata事件,是為了保證視頻的元數據下載完畢后再設置視頻總耗時,避免在play事件觸發時獲取video的duration屬性為空。
提示
視頻的元素據包含時長、尺寸(僅視頻)以及文本軌道等信息。
3.3.3 添加視頻快進慢進按鈕
HTML 5的video元素幾乎帶來了所有傳統播放器都具備的功能,本例將在自定義播放器上加入慢進和快進按鈕。使用Chrome瀏覽器打開網頁文件,點擊屏幕中央的三角播放按鈕,播放器底部出現自定義工具條,同時下方工具條左端出現快慢進按鈕,運行效果如圖3.9所示。

圖3.9 點擊播放按鈕
本例的代碼構建在“3-6.添加視頻快進慢進按鈕.html”的功能基礎之上。下面對增添的代碼部分做一個分析。
字符模板增加快進和慢進HTML結構,代碼如下:
<div class="control backward_control" data-type="backward" title="慢退 "><div></div><div></div></div> <div class="control forward_control" data-type="forward" title="快進 "><div></div><div></div></div>
提示
backward_control和forward_control樣式類,讀者可以參考下載資源源碼。
在HTML結構中,自定義data-type屬性表示對應按鈕元素執行的方法名。快進和慢進在委托方法中對應的方法名為“backward”和“forward”,方法執行腳本如下:
case 'backward': // 自定義工具條慢退 self._playbackRate(-0.1); // 給實例方法_ playbackRate傳入負數播放速度 break; case 'forward': // 自定義工具條快進 self._playbackRate(0.1); break;
如上代碼所示,快慢進執行相同的實例方法_playbackRate,該方法接收1個數字參數,表示增減播放速度,_playbackRate代碼如下:
_playbackRate: function (rate) { this.video.get(0).playbackRate += rate; }
playbackRate屬性表示視頻的播放速度,默認值為1,數值越小播放速度越慢,反之亦然。
3.3.4 處理帶字幕的視頻
本例將給讀者介紹的是在HTML 5視頻中添加字幕。聽起來這像是一項非常復雜的工作,不過HTML 5已經將字幕文件進行抽象獨立,同時非常簡單的就能在任意視頻中添加字幕。本節示例不能直接用瀏覽器打開文件,否則Chrome下會報出“Cross-origin text track load denied by Cross-Origin Resource Sharing policy.”的錯誤信息,表示字幕文件加載違反了跨域資源共享策略。所以,需要將文件部署在Web服務器上,如Apache、Nginx、IIS等。
部署完畢后,用Chrome打開對應網址,點擊屏幕中央的三角播放按鈕,視頻的下方出現字幕,效果如圖3.10所示。

圖3.10 點擊播放按鈕,視頻下方出現字幕
本例的代碼構建在“3-7.處理帶字幕的視頻.html”的基礎上,沒有額外的腳本改動。在HTML中增加字幕結構,代碼如下:
<video width="480" height="320" controls poster="../images/BigBuck.png" preload="none"> <source src="../res/BigBuck.webm" type="video/mp4"> <track label="English subtitles" kind="captions" srclang="en" src="../res/BigBuck.vtt" default> </vidde>
track標簽為視頻規定外部文本軌道,標簽帶有多種新屬性,具體如下:
● default:表示該軌道是默認的。
● kind:表示軌道文本類型,如:captions、chapters、descriptions、metadata、subtitles。
● label:軌道的標簽或標題。
● src:軌道的URL。
● srclang:軌道的語言,若kind屬性值是“subtitle”,則該屬性是必需的。
本例track標簽的軌道文件為1個WebVTT文件。WebVTT文件是一個簡單的純文本,打開“../res/BigBuck.vtt”,代碼如下:
WEBVTT // 文本軌道文件開頭,必填 00:00.000--> 00:01.000 <c>字幕出現---1</c> // 表示可以帶CSS的文本 00:01.000--> 00:02.000 <i>字幕出現---2</i> // 斜體文本 00:02.000--> 00:03.000 <b>字幕出現---3</b> // 粗體文本 00:03.000--> 00:04.000 <u>字幕出現---4</u> // 帶下劃線文本 00:04.000--> 00:05.000 <v.loud>字幕出現---5 // 聲音文本加樣式 00:05.000--> 00:06.000 <v Man>字幕出現---6 // 聲音文本加人物名
在WebVTT文本中,所有c標簽都可以帶CSS樣式,比如<c.demoClass>。還有一種v標簽,也可以帶樣式,同時還可以加入人名。本例給v標簽加上2種樣式類,如下代碼所示:
::cue(.loud) { font-size: 2em; color:Red; } ::cue(v[voice="Man"]) { color: green }
該類聲音文本樣式需要以字符串“::cue”開頭,cue表示指定文本和視頻文件中字幕的時間定位。小括號中間的內容如同CSS,表示選擇器的名稱。其中的“.load”如同一般CSS,表示文本中的樣式類。其中,“v[voice="Man"]”表示對應人物音軌文字的樣式類。
提示
WebVTT還有更多更奇怪的設置,詳情可以參考網址http://dev.w3.org/html5/webvtt/。
- PHP 從入門到項目實踐(超值版)
- Dynamics 365 Application Development
- Leap Motion Development Essentials
- 匯編語言程序設計(第2版)
- The React Workshop
- Building Mapping Applications with QGIS
- Java持續交付
- Active Directory with PowerShell
- Building Microservices with .NET Core
- 機器學習微積分一本通(Python版)
- 寫給程序員的Python教程
- AV1視頻編解碼標準:原理與算法實現
- C語言程序設計實踐
- 零基礎C#學習筆記
- ArcPy and ArcGIS(Second Edition)