創建一個自定義HTML5音頻播放器
Chinese (Traditional) (中文(繁體)) translation by Stypstive (you can also view the original English article)



在本教程中,我將為你介紹HTML5的音頻並且為你展示你可以如何創建屬於你自己的播放器。
如果你希望繞過教程,你可以看看我們在Envato Market上有售的現成的HTML5音頻播放器。 它可以允許你通過各類資源來創建播放列表,以及大量的可自定義選項們。



你同時可以在Envato Studio上找到眾多的HTML5專家來幫助你。
前言
至今為止,將音頻應用到網站項目中依然是一個沉悶的過程,而且很多時候需要依賴第三方插件例如Flash。 由於iPhone臭名昭著的完全不能被接受的插件,以及Adobe關於不再在手機平台上支持Flash的新聞,很多開發人員都希望尋找到其他的方式來將音頻應用到他們的項目中, 這個時候HTML5版本的音頻就是最好的解決問題的辦法。
儘管HTML5提供了一個標準的在網頁上播放音頻文件的能力,但它仍然看起來過於老土,在HTML5能像其他諸如Flash插件一樣提供給你所有選項之前,還有很長的一段路要走。 不過,對於大多數情況來說,它已經足夠了。
簡單HTML5音頻
使用HTML5來將音頻應用到網頁中最簡單的辦法就是使用新的audio標籤 將如下代碼添加到你的HTML5文檔中:
1 |
<audio controls="controls"> |
2 |
<source src="track.ogg" type="audio/ogg" /> |
3 |
<source src="track.mp3" type="audio/mpeg" /> |
4 |
Your browser does not support the audio element. |
5 |
</audio>
|
如果你仔細觀察一下上面的代碼,你可以看到我有一個<audio>標籤的聲明,標籤的聲明,而且我還定義了控制按鈕的屬性,所以我們就可以看到默認的播放器控制按鈕。
在<audio>內部我們嵌套了兩個'src'標籤, 一個用來定義MP3音軌,另外一個用來定義OGG格式。 OGG格式是特別被使用來允許音樂能被在火狐瀏覽器使用的,由於火狐瀏覽器的許可問題它並不能在沒有插件的情況下播放MP3, 一行文字會出現:你的瀏覽器不支持音頻元素, 這讓那些使用並不支持該瀏覽器的用戶知道發生了什麼。



默認的HTML5音頻播放器
HTML5音頻標籤屬性
除了支持總體的HTML5屬性標籤之外還支持一組本身所特有的屬性。
- autoplay- 這個可以被設置為"true"或者留白""來定義當頁面讀取完畢後音軌是否自動播放。
- controls - 在上面的樣例裡面可以看到,這個定義是否顯示自帶的類似‘播放、暫停’等按鈕。
- loop- 這個可以被設置為“loop”並且定義音軌是否會在播放完畢後再重頭開始播放。
- preload- 這個可以被設置為“auto”(這個定義了當頁面打開時文件就會開始被讀取),“metadata”(這個定義了是不是只是讀取音軌信息、標題等),“none ”(這個定義了當頁面打開時瀏覽器並不會預讀任何的文件)。
- src - 這個可以在上面的樣例中看到,它定義了會被音頻標籤播放的音樂文件的url。
把音量開大!
在過去的幾個步驟裡,我們看瞭如何最簡單的創建HTML5音頻, 當我們開始使用音頻標籤配合javascript時,我們可以開始創建一些非常有趣而且有用的音頻播放器。 讓我們來看看jQuery能幫我們做什麼。 當我們在jQuery裡面定義了document ready以後,我們可以創建一個新的音頻變量來控制我們的音頻文件,就想下面這樣簡單:
1 |
var myaudio = new Audio('mysong.mp3');
|
就是這麼簡單! 那麼任何時候,當我們希望對音頻執行一個動作的時候,我們可以使用變量‘myaudio’來觸發它。 底下是一個列表,列出了各類我們可以通過變量進行操作的動作。 記得記個筆記,其中的一些將被我們在接下來的教程中使用來創建我們的音頻播放器。
1 |
myaudio.play(); - This will play the music. |
2 |
myaudio.pause(); - This will stop the music. |
3 |
myaudio.duration; - Returns the length of the music track. |
4 |
myaudio.currentTime = 0; - This will rewind the audio to the beginning. |
5 |
myaudio.loop = true; - This will make the audio track loop. |
6 |
myaudio.muted = true; - This will mute the track |
如果你希望一個功能在音頻播放完畢的時候被訪問,那麼你可以使用‘myaudio.addEventListener('ended),myfunc’ - 這個會在音頻播放完畢時請求一次'myfunc()'。
創建HTML5音頻播放器:結構
現在你已經有了一些對HTML5音頻的以及最基本的知識的了解,是時候來做一些練習並創建一個自定義的HTML5音頻播放器了。 我將把設計的那個步驟排除在本教程之外,但是你可以下載附件裡的源文件並查看PSD格式文件,以此來獲取一些概念並了解我是如何將他們組合在一起的。
在文檔的頂部是HTML5的doctype, 雅虎CSS Reset,Google在線字體‘Lobster’以及標題, 然後我們有了最新版本的jQuery以及自定義JavaScript文件js.js。 最後我們將讀取html5slider.js,這允許火狐來顯示HTML5中input的range類型,我們將使用它來製作音頻播放器裡的拖動條。
1 |
<!DOCTYPE html>
|
2 |
<head>
|
3 |
<title>HTML5 Audio Tutorial</title> |
4 |
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/3.3.0/build/cssreset/reset-min.css"> |
5 |
<link href='http://fonts.googleapis.com/css?family=Lobster' rel='stylesheet' type='text/css'> |
6 |
<link rel="stylesheet" type="text/css" href="css/style.css"> |
7 |
<script src="http://code.jQuery.com/jQuery-latest.js" type="text/javascript"></script> |
8 |
<script type="text/javascript" src="js/js.js"></script> |
9 |
<script type="text/javascript" src="js/html5slider.js"></script> |
10 |
</head>
|
在h1標題之後,我創建了一個div並賦予了class“container”和“gradient”。 我創建了一個分離的漸變(gradient)class,這樣我們將再一次使用它到其他的一些元素上。 在".container"之內,我添加了一個圖片(它將會是唱片封面),然後三個錨點標籤將會作為播放器的控制按鈕來工作。 在他們之間,你會看到一個拖動條/HTML5 range input區域。
1 |
<body>
|
2 |
|
3 |
<h1>HTML 5 Audio Player</h1> |
4 |
|
5 |
<div class="container gradient"> |
6 |
|
7 |
<img class="cover" src="images/cover.jpg" alt=""> |
8 |
|
9 |
<div class="player gradient"> |
10 |
|
11 |
<a class="button gradient" id="play" href="" title=""></a> |
12 |
<a class="button gradient" id="mute" href="" title=""></a> |
13 |
|
14 |
<input type="range" id="seek" value="0" max=""/> |
15 |
|
16 |
<a class="button gradient" id="close" href="" title=""></a> |
17 |
|
18 |
</div><!-- / player --> |
19 |
|
20 |
</div><!-- / Container--> |
21 |
</body>
|
22 |
</html>
|
創建HTML5音頻播放器:樣式
我並不會在本教程中囊括所有方面的CSS細節,反之,我將給你一個概觀和基本的註解到一些特定的部分,那些你可能希望更加註意的部分。
在下面的代碼中,我為播放器創建了一個漸變效果,它是由CSS漸變編輯器所生成的。 接下來,我創建了一個播放器的“.container”以及一些CSS3的過渡。
你會發現,我同時使用了CSS3的盒子尺寸的屬性集來設置‘border-box’。 這個允許我們在容器的周圍創建一個10像素的padding,包括在我已經定義的寬度裡面,在這個樣例中是427像素。 如果我並沒有使用這個padding,那麼結果將會是在427像素的基礎上再添加額外的寬度,這樣就使容器大於我想要的尺寸了。 在現今,使用* {box-sizing: border-box;} 已經是一件很正常的事情了,這個可以創建一個更直觀的方式來添加樣式。
我同時添加了一些CSS3的過渡到“.coverlarge”使播放器第一次打開的時候生成一些漂亮的過渡效果。 這個CSS有可能看起來有一點過於的誇張了,但是它們的絕大部分都是由瀏覽器的prefix組成的,這是來確保音頻播放器在不同瀏覽器之間都看起來完全是相同的。
1 |
.gradient { |
2 |
border: 1px solid black; |
3 |
|
4 |
-webkit-box-shadow: inset 0 1px 0px rgba(255,255,255,.2); |
5 |
-moz-box-shadow: inset 0 1px 0px rgba(255,255,255,.2); |
6 |
box-shadow: inset 0 1px 0px rgba(255,255,255,.2); |
7 |
background: #494949; /* Old browsers */ |
8 |
background: -webkit-linear-gradient(top, #494949 0%, #434242 31%, #393838 55%, #242323 83%, #1b1a1a 100%, #161515 100%, #0b0b0b 100%); |
9 |
|
10 |
background: -moz-linear-gradient(top, #494949 0%, #434242 31%, #393838 55%, #242323 83%, #1b1a1a 100%, #161515 100%, #0b0b0b 100%); |
11 |
background: -o-linear-gradient(top, #494949 0%, #434242 31%, #393838 55%, #242323 83%, #1b1a1a 100%, #161515 100%, #0b0b0b 100%); |
12 |
background: -ms-linear-gradient(top, #494949 0%, #434242 31%, #393838 55%, #242323 83%, #1b1a1a 100%, #161515 100%, #0b0b0b 100%); |
13 |
background: linear-gradient(top, #494949 0%, #434242 31%, #393838 55%, #242323 83%, #1b1a1a 100%, #161515 100%, #0b0b0b 100%); /* W3C */ |
14 |
-image filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#494949', endColorstr='#0b0b0b',GradientType=0 ); /* IE6-9 */ |
15 |
}
|
16 |
|
17 |
.container { |
18 |
-webkit-transition: all .7s ease; |
19 |
-moz-transition: all .7s ease; |
20 |
-o-transition: all .7s ease; |
21 |
-ms-transition: all .7s ease; |
22 |
transition: all .7s ease; |
23 |
position: absolute; |
24 |
width: 427px; |
25 |
height: 70px; |
26 |
|
27 |
-webkit-border-radius: 10px; |
28 |
-moz-border-radius: 10px; |
29 |
border-radius: 10px; |
30 |
|
31 |
-webkit-box-shadow: 0px 0px 13px rgba(0,0,0,.3),inset 0 1px 0px rgba(255,255,255,.2); |
32 |
-moz-box-shadow: 0px 0px 13px rgba(0,0,0,.3),inset 0 1px 0px rgba(255,255,255,.2); |
33 |
box-shadow: 0px 0px 13px rgba(0,0,0,.3),inset 0 1px 0px rgba(255,255,255,.2); |
34 |
top: 50%; |
35 |
left: 50%; |
36 |
margin: -214px 0px 0px -214px; |
37 |
padding: 10px; |
38 |
|
39 |
-webkit-box-sizing: border-box; |
40 |
-moz-box-sizing: border-box; |
41 |
-ms-box-sizing: border-box; |
42 |
box-sizing: border-box; |
43 |
}
|
44 |
|
45 |
|
46 |
.containerLarge { |
47 |
height: 427px; |
48 |
}
|
49 |
|
50 |
.cover { |
51 |
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; |
52 |
filter: alpha(opacity=0); |
53 |
opacity: 0; |
54 |
width: 398px; |
55 |
height: 10px; |
56 |
border: 2px solid black; |
57 |
|
58 |
-webkit-border-radius: 5px; |
59 |
-moz-border-radius: 5px; |
60 |
border-radius: 5px; |
61 |
|
62 |
-webkit-box-shadow: inset 0px 5px 5px rgba(0,0,0,1); |
63 |
-moz-box-shadow: inset 0px 5px 5px rgba(0,0,0,1); |
64 |
box-shadow: inset 0px 5px 5px rgba(0,0,0,1); |
65 |
}
|
66 |
|
67 |
.coverLarge { |
68 |
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; |
69 |
filter: alpha(opacity=100); |
70 |
opacity: 1; |
71 |
height: 398px; |
72 |
|
73 |
-webkit-transition: opacity .7s ease; |
74 |
-moz-transition: opacity .7s ease; |
75 |
-o-transition: opacity .7s ease; |
76 |
-ms-transition: opacity .7s ease; |
77 |
transition: opacity .7s ease; |
78 |
|
79 |
-webkit-transition-delay: .5s; |
80 |
-moz-transition-delay: .5s; |
81 |
-o-transition-delay: .5s; |
82 |
-ms-transition-delay: .5s; |
83 |
transition-delay: .5s; |
84 |
}
|



這就是在當前情況下播放器的樣子
當播放器的容器完成了以後,是時候來創建一個實際的控制按鈕了, 大部分按鈕都是使用CSS sprites來創建的。
不幸的是,IE暫時還不支持HTML5中input的range屬性,所以我決定對於IE用戶來說暫時不顯示拖動條。 如果你正處於一個必須要實現這個效果的境地,你可以使用jQuery UI slider來使用想死的方式來實現我說的效果。 同樣的,我已經簡單的用代碼隱藏了input{display:none\9!important;},這樣的基本代碼可以為ie用戶屏蔽顯示input(看看這個Stack Overflow上的討論帖來獲得更多關於\ 9的信息)。
HTML5的range滑動條的問題是僅僅有比較少的瀏覽器支持自定義樣式;大部分都是webkit瀏覽器支持(Chrome和Safari), 不幸的是,例如Opera和Firefox將只顯示最基本的range滑動條。 如果你確實需要為所有瀏覽器來自定義樣式,那麼你可以使用我們上面所提到的jQuery UI slider。 你可以看到為webkit瀏覽器自定義樣式的設定是在input::-webkit-slider-thumb屬性裡。
1 |
.player { |
2 |
-webkit-box-sizing: border-box; |
3 |
-moz-box-sizing: border-box; |
4 |
-ms-box-sizing: border-box; |
5 |
box-sizing: border-box; |
6 |
position: absolute; |
7 |
width: 300px; |
8 |
bottom: 10px; |
9 |
width: 95%; |
10 |
|
11 |
-webkit-border-radius: 3px; |
12 |
-moz-border-radius: 3px; |
13 |
border-radius: 3px; |
14 |
padding: 5px; |
15 |
}
|
16 |
|
17 |
.button { |
18 |
display: block; |
19 |
width: 34px; |
20 |
height: 34px; |
21 |
background-image: url(../images/sprite.png); |
22 |
background-repeat: no-repeat; |
23 |
float: left; |
24 |
margin-right: 5px; |
25 |
}
|
26 |
|
27 |
#play { |
28 |
background-position: 6px 5px; |
29 |
}
|
30 |
|
31 |
#pause { |
32 |
background-position: -32px 5px; |
33 |
}
|
34 |
|
35 |
#mute { |
36 |
background-position: -63px 5px; |
37 |
}
|
38 |
|
39 |
#muted { |
40 |
background-position: -106px 5px; |
41 |
}
|
42 |
|
43 |
input[type="range"] { |
44 |
width: 250px; |
45 |
margin-top: -5px; |
46 |
}
|
47 |
|
48 |
#close { |
49 |
float: right; |
50 |
background-position: -146px 5px; |
51 |
display: none; |
52 |
}
|
53 |
|
54 |
.volume { |
55 |
position: absolute; |
56 |
height: 100px; |
57 |
width: 34px; |
58 |
border: 1px solid black; |
59 |
background-color: #242323; |
60 |
top: -97px; |
61 |
display: none; |
62 |
}
|
63 |
input{ |
64 |
display:none\9!important; |
65 |
}
|
66 |
input[type="range"] { |
67 |
-webkit-appearance: none; |
68 |
border: 1px solid black; |
69 |
position: absolute; |
70 |
top: 18px; |
71 |
display: block; |
72 |
width: 63%; |
73 |
height: 15px; |
74 |
|
75 |
-webkit-border-radius: 20px; |
76 |
-moz-border-radius: 20px; |
77 |
border-radius: 20px; |
78 |
background-color: #242323; |
79 |
left: 90px; |
80 |
|
81 |
-webkit-box-shadow: inset 0px 4px 4px rgba(0,0,0,.6); |
82 |
-moz-box-shadow: inset 0px 4px 4px rgba(0,0,0,.6); |
83 |
box-shadow: inset 0px 4px 4px rgba(0,0,0,.6); |
84 |
}
|
85 |
|
86 |
input::-webkit-slider-thumb { |
87 |
-webkit-appearance: none; |
88 |
width: 20px; |
89 |
height: 20px; |
90 |
border:1px solid black; |
91 |
|
92 |
-webkit-border-radius: 10px; |
93 |
border-radius: 10px; |
94 |
background: #80e4df; /* Old browsers */ |
95 |
background: -webkit-linear-gradient(top, #80e4df 0%, #75dbd6 13%, #5ec4bf 33%, #57bbb6 47%, #419d99 80%, #378f8b 100%); |
96 |
|
97 |
background: -moz-linear-gradient(top, #80e4df 0%, #75dbd6 13%, #5ec4bf 33%, #57bbb6 47%, #419d99 80%, #378f8b 100%); |
98 |
background: -o-linear-gradient(top, #80e4df 0%, #75dbd6 13%, #5ec4bf 33%, #57bbb6 47%, #419d99 80%, #378f8b 100%); |
99 |
background: linear-gradient(top, #80e4df 0%, #75dbd6 13%, #5ec4bf 33%, #57bbb6 47%, #419d99 80%, #378f8b 100%); /* W3C */ |
100 |
}
|
創建HTML5音頻播放器:jQuery
一但樣式表和結構完成了以後,我們就需要開始來創建我們實際的播放器了。 我們可以用javascript的框架jQuery來完成它。 一但jQuery中document ready被聲明了以後,我們就可以創建用於存儲我們jQuery物體的變量了。
1 |
container = $('.container');
|
2 |
cover = $('.cover');
|
3 |
play = $('#play');
|
4 |
pause = $('#pause');
|
5 |
mute = $('#mute');
|
6 |
muted = $('#muted');
|
7 |
close = $('#close');
|
8 |
song = new Audio('music/track1.ogg','music/track1.mp3');
|
9 |
duration = song.duration; |
在“song(歌曲)”變量中,你可以看到我們定義了兩個音軌。 其中OGG格式是為了火狐瀏覽器,而MP3是為了其他瀏覽器的。 接著我創建了一個if的條件語句聲明,這樣我們可以檢查瀏覽器是否能播放MP3。 如果它可以,那麼我們將改變“song”變量的鏈接到MP3音軌 - 如果它不能播放就讀取‘OGG’格式。
1 |
if (song.canPlayType('audio/mpeg;')) {
|
2 |
song.type= 'audio/mpeg'; |
3 |
song.src= 'music/track1.mp3'; |
4 |
} else {
|
5 |
song.type= 'audio/ogg'; |
6 |
song.src= 'music/track1.ogg'; |
7 |
} |
下一步我們將要創建一個點擊的功能,這個將允許我們播放和暫停音樂。完全替換播放按鈕和暫停按鈕。 我使用了音頻動作play()來開始音頻,然後使用jQuery功能replaceWith這樣基本可以
我同時添加了“coverLarge”和“containerLarge”class到“container”和“cover”上。 由於我早先已經添加了CSS3的過渡到CSS裡,所以當音頻開始播放的時候會顯示出漂亮的效果。 “暫停”的工作方式是相似的,但是並沒有過渡效果。 當點擊時,它將“播放”按鈕替換為了“暫停”按鈕。
1 |
play.live('click', function(e) {
|
2 |
e.preventDefault(); |
3 |
song.play(); |
4 |
|
5 |
$(this).replaceWith('<a class="button gradient" id="pause" href="" title=""></a>');
|
6 |
container.addClass('containerLarge');
|
7 |
cover.addClass('coverLarge');
|
8 |
$('#close').fadeIn(300);
|
9 |
$('#seek').attr('max',song.duration);
|
10 |
}); |
11 |
|
12 |
pause.live('click', function(e) {
|
13 |
e.preventDefault(); |
14 |
song.pause(); |
15 |
$(this).replaceWith('<a class="button gradient" id="play" href="" title=""></a>');
|
16 |
|
17 |
}); |
靜音和已靜音按鈕的工作方式和播放暫停按鈕也是基本相同的,但是訪問相關動作和替換按鈕的時候使用相應的替代。
1 |
mute.live('click', function(e) {
|
2 |
e.preventDefault(); |
3 |
song.volume = 0; |
4 |
$(this).replaceWith('<a class="button gradient" id="muted" href="" title=""></a>');
|
5 |
|
6 |
}); |
7 |
|
8 |
muted.live('click', function(e) {
|
9 |
e.preventDefault(); |
10 |
song.volume = 1; |
11 |
$(this).replaceWith('<a class="button gradient" id="mute" href="" title=""></a>');
|
12 |
|
13 |
}); |
當用戶點擊“關閉”按鈕的時候我們訪問jQuery來移除“containerLarge”和“coverLarge”class。 這樣會隱藏封面並關閉播放器的支持。 接下來我們通過pause()動作來暫停播放器,然後重置音頻的currentTime到0,這樣就將播放器重置為開始的狀態。
1 |
$('#close').click(function(e) {
|
2 |
e.preventDefault(); |
3 |
container.removeClass('containerLarge');
|
4 |
cover.removeClass('coverLarge');
|
5 |
song.pause(); |
6 |
song.currentTime = 0; |
7 |
$('#pause').replaceWith('<a class="button gradient" id="play" href="" title=""></a>');
|
8 |
$('#close').fadeOut(300);
|
9 |
}); |
現在是時候繼續來完善拖動條了,我們給了它一個id為“seek”, 第一個功能是允許我們移動拖動條到音頻的任意位置, 這個需要在檢測是否有人移動了拖動條的前提下來實現, 我們然後設置song.currentTime來匹配拖動條拖到的位置的歌曲時間。 我們同時設置最大屬性來定義歌曲的總時長。
1 |
$("#seek").bind("change", function() {
|
2 |
song.currentTime = $(this).val(); |
3 |
$("#seek").attr("max", song.duration);
|
4 |
}); |
最後一部分的jQuery是讓“#seek”拖動條保持在音頻播放的時候跟隨並不斷的移動。 我們將要添加一個事件監聽器然後當音頻時間更新的時候我們就呼叫這個function。 我設置了一個"curtime"變量來獲得當前歌曲的時間, 然後更新拖動條的值來反映出當前音頻時間的位置。
1 |
song.addEventListener('timeupdate',function (){
|
2 |
curtime = parseInt(song.currentTime, 10); |
3 |
$("#seek").attr("value", curtime);
|
4 |
}); |
然後你就搞定啦! 一個你可以應用到你的網站或者app的HTML5音頻播放器。
結語
正如我之前提到的,HTML5音頻依然是一個不是很花哨而且還有待提升的, 在當天來說音頻是設計來播放音樂的,而且會因此不斷的從服務器獲取音頻流,這樣在某一些瀏覽器會導致playback發生問題, 雖說這不總成為問題,但是卻意味著有時候它會在完整的下載音頻之前就開始播放。
如果你希望使用HTML5音頻來作為遊戲或者含有諸多音頻app的音效時,這可能會成為潛在的問題, 由於這個原因, 我們在Google的朋友已經有了一個方式來改進音頻標籤的弱項。 Google已經創建並向W3C提出了一項議題“Web Audio API”, 這個被證實會變的比HTML5的音頻標籤更牛氣,不過在當下有一個問題(你猜是啥?)它只能在Chrome裡被支持。
你可以閱讀更多關於Google的Web Audio API並在Google code閱覽一些樣例,或者你也可以看看這個web audio specification。
我希望你享受學習關於HTML5音頻的知識,以及關於如何創建你自己的播放器的方式。 我的播放器包含了最基本的控制,但是沒有任何人阻止你來添加更多功能,諸如音量控制甚至添加你自己的自定義動畫等等, 你只需要稍微的用一點心去思考,再加上一點點實踐,你可以創建一些非常不錯的音頻播放器。 下載源代碼,我期待能看到你能做出什麼不一樣的成果!
如果你希望看到更多選項關於HTML5裡如何製作音頻播放器或是其他媒體,看看這個Envato Market上的HTML5媒體項目吧。



