首先,在 iPad (iOS) 的 Safari 有一點很特別,根據 Apple 官方文件:
中所述,基於保護使用者的權益,如果使用者沒有「按按鈕」,Safari 不會自動載入 Audio 或 Video。這也是為什麼我們新增一個 Audio 物件後,即使在程式中下了 play() 指令,它不會開始播放聲音的原因。必須把 play() 指令放到滑鼠或觸控的事件中,被動的由使用者去觸發過它,才能開始載入檔案並播放聲音。另外,iOS 無法同時播放多個聲音檔,一次只允許播放一個聲音。因此,給 iOS 用的,要考慮這兩點。
如果是要當遊戲音效,iOS 不會自動播放,那不就白搭了?沒關係,我的做法是,在程式最前面放一個使用說明的畫面,要使用者按下按鈕後才開始玩,就利用這個機會,順便由使用者手動執行了一次 play() 指令,這樣,之後要播放聲音,只要用同一個 Audio 更改 src ,指定別的聲音檔,就不再受要使用者按按鈕才能載入並播放的限制了。
LimeJS 中的 Audio 使用 lime.audio.Audio ,它只提供了基本的 play , stop 及兩個用來顯示狀態的 isLoaded 和 isPlaying。如果,想用前述的方法,只重新指定 Audio 檔案的路徑,就得自己再將 lime.audio.Audio 增強。
底下 w3schools 的文件很有參考價值:
例如,假設我用
var sound = new lime.audio.Audio('test.mp3');
加了一個聲音物件載入 test.mp3 檔案,想要取得聲音檔的總長度(秒)及已播放的時間(秒),可以利用下面的語法得到:
- sound.baseElement.duration
- sound.baseElement.currentTime
想要指定另外一個聲音檔,可以利用下面的語法:
sound.baseElement.src = 'theSecondSound.mp3';
當然,我們也可以用來監聽「事件」,寫一些對應的功能,例如,想製作一個播放時間的指示器,就可以監聽「timeupdate」,例如:
透過 w3schools 的參考文件,對於 Audio 的操作,已能掌握大部份。目前尚不知如何以 base64 來將 mp3 檔案編碼後直接餵給 iOS 的 Safari ,如果這項功能可以實現,音效檔離線使用的問題就有解了。
下面這個 AudioSprite 滿有趣的,它將多個音效放在一個聲音檔內,然後利用每個音效的時間長度來區分是哪個音效,ex. A+B+C = 10+50+30 ,當我要播放 B 音效時就是播放聲音檔的 11~60 秒,要播放 C 音效時就是播放聲音檔的 61~90 秒。
這樣的話,在 iOS 上較不會有延遲的狀況 ,感覺較流暢。缺點是前置的聲音檔製作要花一點工夫。
goog.events.listen(sound.baseElement,'timeupdate',function(){
......
......
});
當聲音在播放時,會去執行 ...... 所指定的程式碼,如果配合取得 sound.baseElement.duration 及 sound.baseElement.currentTime 的值並加以計算,即可顯示播放狀態。
另外,如果我們在新建完 Audio 物件後,在它還沒有載入完成就馬上執行 play() 的播放指令,也會失敗。「canplay」事件是在已經準備就緒時觸發的事件,可以好好好的利用。
另外,如果我們在新建完 Audio 物件後,在它還沒有載入完成就馬上執行 play() 的播放指令,也會失敗。「canplay」事件是在已經準備就緒時觸發的事件,可以好好好的利用。
透過 w3schools 的參考文件,對於 Audio 的操作,已能掌握大部份。目前尚不知如何以 base64 來將 mp3 檔案編碼後直接餵給 iOS 的 Safari ,如果這項功能可以實現,音效檔離線使用的問題就有解了。
下面這個 AudioSprite 滿有趣的,它將多個音效放在一個聲音檔內,然後利用每個音效的時間長度來區分是哪個音效,ex. A+B+C = 10+50+30 ,當我要播放 B 音效時就是播放聲音檔的 11~60 秒,要播放 C 音效時就是播放聲音檔的 61~90 秒。
- AudioSprite :
https://github.com/koggdal/AudioSprite - AudioSprite 的範例
這樣的話,在 iOS 上較不會有延遲的狀況 ,感覺較流暢。缺點是前置的聲音檔製作要花一點工夫。
救命啊...萬一遇到換頁怎辦...
回覆刪除