日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
HTML5中視頻和音頻核心事件講解

HTML 5中的視頻和音頻中有不少核心的事件,其中有的比較容易理解,基本能從字面就解析了,比如“play”事件就很好理解。而其他有的事件則需要花費(fèi)點(diǎn)心思,特別是“progress”事件。因此,在本文中,將帶領(lǐng)讀者研究HTML 5視頻和音頻中重要的事件,探究這些事件是應(yīng)該在什么時(shí)候使用以及其中的重要相關(guān)屬性。我們也將看下這些事件在當(dāng)今不同瀏覽器中的差異。為了本文的測(cè)試,使用的瀏覽器如下:Opera 12、Chrome 28、IE 10、Firefox 22、Safari 5(桌面版)和Mobile Safari 6(iOS版本)。

播放相關(guān)的事件

我們先來看下視頻和音頻中的playback事件。plackback事件發(fā)生的時(shí)機(jī)在播放媒體或停止媒體中,這個(gè)比較好理解,下面來仔細(xì)研究一下。其中“play”和“pause”事件分別在媒體播放和停止的時(shí)候觸發(fā),但也有一個(gè)“ended”事件,該事件是在媒體播放完畢到達(dá)***的時(shí)候觸發(fā)-無論是正常情況下的結(jié)束或是用戶自己動(dòng)播放條到媒體文件的***。

這兩個(gè)對(duì)應(yīng)事件的觸發(fā)很簡(jiǎn)單,只需要調(diào)用play()和pause()方法就可以了。它們也有對(duì)應(yīng)的屬性,其中.paused屬性默認(rèn)設(shè)置為true,而.ended屬性默認(rèn)是設(shè)置為false的,當(dāng)然當(dāng)媒體文件播放到***的時(shí)候,.ended屬性則變?yōu)閠rue。

然而,在Opera、Safari和IE 10中,請(qǐng)注意有個(gè)區(qū)別,就是即使媒體播放完畢,其中的.paused屬性依然為false(從邏輯上說,媒體已經(jīng)播放完畢了)。這樣一個(gè)實(shí)際的結(jié)果是play/pause按鈕的事件都不會(huì)觸發(fā)了,看下面的例子:

 
 
 
 
  1. button.addEventListener('click', function(e) 
  2.   if(media.paused) 
  3.   { 
  4.     media.play(); 
  5.   } 
  6.   else 
  7.   { 
  8.     media.pause(); 
  9.   } 
  10. }, false); 

也就是說,當(dāng)視頻結(jié)束后,其pause()事件依然能調(diào)用。我們可以通過一個(gè)小技巧去修正這個(gè)問題,如下代碼所示:

 
 
 
 
  1. media.addEventListener('ended', function(e)  
  2.  
  3. {  
  4.  
  5.   media.pause();  
  6.  
  7. }, false);  

也就是在監(jiān)聽ended事件中,主動(dòng)調(diào)用media.pause()方法就可以了。在Firefox和Chrome的***版本中,已經(jīng)修正了這個(gè)問題。

關(guān)于加載事件

加載事件總是在媒體加載(或加載失敗)的時(shí)候發(fā)生。加載事件受到加載媒體狀態(tài)的影響,比如是否使用了preload屬性又或者是媒體是否緩存了。下面我們來逐一分析下其中關(guān)鍵的事件,首先是“l(fā)oadstart”事件,含義是讓瀏覽器剛開始的時(shí)候去尋找獲得數(shù)據(jù)。但要注意的是,loadstart并不意味著就任何數(shù)據(jù)就會(huì)馬上加載,還要看preload屬性的值的設(shè)置。如果preload(預(yù)裝載的值)設(shè)置為“none”的話,則“l(fā)oadstart”事件就是唯一在播放視頻前觸發(fā)的事件。如果preload屬性設(shè)置為“metadata”或者是“auto”,則會(huì)觸發(fā)“progress”和“l(fā)oadmetadata”事件(如果沒預(yù)加載的話,這兩個(gè)事件也會(huì)觸發(fā),但不會(huì)在播放前發(fā)生)。

在下一節(jié)中,我們才學(xué)習(xí)“progress”事件,由于其比較復(fù)雜。我們先來學(xué)習(xí)比較簡(jiǎn)單的“l(fā)oadedmetadata”事件。正如字面的含義,瀏覽器僅僅加載媒體的元數(shù)據(jù)信息而已,比如其長(zhǎng)度.duration(是一個(gè)浮點(diǎn)數(shù)而不是默認(rèn)的NaN)。

當(dāng)然,“l(fā)oadedmetadata”事件只有在確認(rèn)能加載媒體文件后才能加載,換句話說,如果某個(gè)媒體問題文件不能加載(比如404錯(cuò)誤),則會(huì)直接產(chǎn)生error事件,當(dāng)然也不可能繼續(xù)運(yùn)行相關(guān)的播放事件了。

這里,又要提醒用戶有的瀏覽器中是有差別的。在Mobile Safari中,preload的屬性其實(shí)是沒聲明的,就等于設(shè)置為“none”一樣了。但在IE 10中,又有不同了,其中媒體的元數(shù)據(jù)默認(rèn)是自動(dòng)加載的,所以preload設(shè)置為none其實(shí)跟設(shè)置為metadata的作用是一樣的。

在“l(fā)oadedmetadata”事件觸發(fā)后,接下來的重要事件就是“canplay”,這個(gè)是瀏覽器用來確認(rèn)是否已經(jīng)裝載足夠的媒體信息到瀏覽器中能播放一個(gè)事件。如果preload屬性設(shè)置為“auto”,則在數(shù)據(jù)裝載后大概幾秒,“canplay”事件就會(huì)觸發(fā);如果preload設(shè)置為“metadata”或者是“none”,則直到播放開始時(shí)才會(huì)觸發(fā)。這個(gè)規(guī)則對(duì)Chrome瀏覽器來說是例外的,在Chrome中,即使只是加載元數(shù)據(jù)階段,“canplay”事件也會(huì)觸發(fā)。

同時(shí)也有僅接著的事件叫“canplaythrough”,這個(gè)事件其實(shí)是給瀏覽器根據(jù)當(dāng)前網(wǎng)絡(luò)狀況去判斷是否已經(jīng)加載了足夠的媒體片斷而支撐基本的播放。所以這個(gè)事件要在數(shù)據(jù)被預(yù)加載大概幾秒后才會(huì)觸發(fā)。

在實(shí)際情況下,“canplaythrough”事件基本是沒啥作用的,因?yàn)镾afari根本不會(huì)觸發(fā)這個(gè)事件,而Opera和Chrome則在“canplay”事件觸發(fā)后馬上就觸發(fā)這個(gè)事件,只有FireFox和IE 10實(shí)現(xiàn)了這個(gè)事件。

所以實(shí)際上,開發(fā)者最應(yīng)該關(guān)心的是監(jiān)視“progress”事件,以了解媒體到底加載了多少(必要的時(shí)候可以計(jì)算媒體的下載速度)。

Progress事件

接下來我們重點(diǎn)學(xué)習(xí)下progress事件。該事件在數(shù)據(jù)正在下載的時(shí)候會(huì)觸發(fā)。所以當(dāng)preload設(shè)置為none的時(shí)候,progress事件在知道播放事件真正開始前是不會(huì)觸發(fā)的。如果preload設(shè)置為“metadata”,則該事件會(huì)短暫觸發(fā)大概幾秒,然后停止,直到真正的播放行為開始時(shí)才觸發(fā);如果preload設(shè)置為“auto”,則會(huì)觸發(fā)一直直到整個(gè)媒體文件下載完畢。

無論preload如何設(shè)置,一旦用戶開始進(jìn)行播放的行為,則瀏覽器會(huì)開始下載整個(gè)媒體文件,則會(huì)持續(xù)觸發(fā)progress事件,一直直到整個(gè)文件下載完畢,即使視頻被暫停。

當(dāng)數(shù)據(jù)下載后,則我們需要了解如何用時(shí)間表達(dá)這個(gè)progress的事件,則對(duì)接下來深入了解progress事件是十分重要的。當(dāng)數(shù)據(jù)開始加載時(shí),會(huì)創(chuàng)建表示媒體播放時(shí)間的范圍,比如一旦頭10秒的數(shù)據(jù)已經(jīng)加載,則以數(shù)組的方式記錄了開始和結(jié)束時(shí)間,如下的方式表示:

 
 
 
 
  1. [0,10] 

當(dāng)然,實(shí)際上是會(huì)有多個(gè)時(shí)間范圍存在的,比如用戶手工使用播放器的進(jìn)度條去移動(dòng)到想要的位置,則瀏覽器會(huì)忽略當(dāng)前的時(shí)間范圍而加載新的部分而不是象 Flash那樣重新加載兩個(gè)時(shí)間點(diǎn)之間的部分。

比如我們加載10秒的視頻后,跳到兩分鐘后的片斷繼續(xù)播放另外的10秒,則有兩個(gè)時(shí)間范圍,用如下的方式表達(dá):

 
 
 
 
  1.   [0,10], 
  2.   [120,130] 

假設(shè)用戶這個(gè)時(shí)候又回看舊的片斷,則繼續(xù)又增加一個(gè)時(shí)間范圍的數(shù)組,如:

 
 
 
 
  1.   [0,10], 
  2.   [60,70], 
  3.   [120,130] 

如果從60秒開始看到130秒結(jié)束,則***的時(shí)間范圍合拼為:

 
 
 
 
  1.   [0,10], 
  2.   [60,130] 

上面的例子只是簡(jiǎn)單說明在播放媒體中,時(shí)間的范圍是如何運(yùn)作的,當(dāng)然實(shí)際上的數(shù)據(jù)保存不是這個(gè)樣子。實(shí)際上媒體都有一個(gè).buffered對(duì)象以表示時(shí)間范圍。.buffered對(duì)象有一個(gè).length長(zhǎng)度屬性表示有多少段時(shí)間范圍,并且有對(duì)應(yīng)的start()和end()方法, 所以我們可以將buffered的數(shù)據(jù)轉(zhuǎn)換為二維數(shù)組,如下代碼所示:

 
 
 
 
  1. var ranges = []; 
  2. for(var i = 0; i < media.buffered.length; i ++) 
  3.   ranges.push([ 
  4.     media.buffered.start(i), 
  5.     media.buffered.end(i) 
  6.     ]); 

***,我們可以自定義progress事件如下:

 
 
 
 
  1. media.addEventListener('progress', function() 
  2.   var ranges = []; 
  3.   for(var i = 0; i < media.buffered.length; i ++) 
  4.   { 
  5.     ranges.push([ 
  6.       media.buffered.start(i), 
  7.       media.buffered.end(i) 
  8.       ]); 
  9.   } 
  10. }, false); 

有了這個(gè)方法,則我們可以針對(duì)progress事件進(jìn)行一些定制開發(fā)。比如我們可以實(shí)現(xiàn)一個(gè)簡(jiǎn)單的播放視頻,并且提供一個(gè)額外的進(jìn)度條,在視頻加載過程中能看到其進(jìn)度。其實(shí)際的運(yùn)行效果請(qǐng)參考:http://jspro.brothercake.com/media-events/progress.html ,下面是一個(gè)運(yùn)行效果截圖:

下面選取其中的代碼片斷講解其核心原理:

 
 
 
 
  1. function onprogress() 
  2.         { 
  3.             //獲得buffered數(shù)據(jù) 
  4.             var ranges = []; 
  5.             for(var i = 0; i < media.buffered.length; i ++) 
  6.             { 
  7.                 ranges.push([ 
  8.                     media.buffered.start(i), 
  9.                     media.buffered.end(i) 
  10.                     ]); 
  11.             } 
  12.              
  13.             //獲得在容器中的當(dāng)前進(jìn)度 
  14.             var spans = progress.getElementsByTagName('span'); 
  15.              
  16.             //如果還沒有加載完畢則繼續(xù)加載 
  17.             while(spans.length < media.buffered.length) 
  18.             { 
  19.                 progress.appendChild(document.createElement('span')); 
  20.             } 
  21.             while(spans.length > media.buffered.length) 
  22.             { 
  23.                 progress.removeChild(progress.lastChild); 
  24.             } 
  25.                  
  26.              
  27.             for(var i = 0; i < media.buffered.length; i ++) 
  28.             { 
  29.                 spans[i].style.left = Math.round 
  30.                 ( 
  31.                     (100 / media.duration)                  *  
  32.                     ranges[i][0] 
  33.                 )  
  34.                 + '%'; 
  35.                  
  36.                 spans[i].style.width = Math.round 
  37.                 ( 
  38.                     (100 / media.duration)                  *  
  39.                     (ranges[i][1] - ranges[i][0]) 
  40.                 )  
  41.                 + '%'; 
  42.             } 
  43.         } 

在上面的代碼段中,使用的是設(shè)置的寬度去代表進(jìn)度條的每一個(gè)格的寬度,首先獲得buffered數(shù)據(jù),存放到數(shù)據(jù)ranges中,然后判斷媒體文件是否加載完畢,如果還沒加載完畢,則繼續(xù)往DOM中添加標(biāo)簽,而這個(gè)span標(biāo)簽的寬度和樣式則是通過上面的代碼按百分比計(jì)算出來。

***,用戶可以通過http://jspro.brothercake.com/media-events/events.html的例子,學(xué)習(xí)到本文中提到的在媒體加載前、加載中和加載后瀏覽器的相關(guān)事件,在這個(gè)例子中會(huì)輸出相關(guān)的日志。


當(dāng)前標(biāo)題:HTML5中視頻和音頻核心事件講解
當(dāng)前路徑:http://m.5511xx.com/article/dpeghij.html