audio.html 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta charset="utf-8"/>
  5. <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
  6. <meta name="HandheldFriendly" content="true"/>
  7. <meta name="MobileOptimized" content="320"/>
  8. <title>Hello H5+ 2</title>
  9. <script type="text/javascript" src="../js/common.js"></script>
  10. <script type="text/javascript">
  11. var gentry=null,hl=null,le=null;
  12. var er=null,ep=null;
  13. var bUpdated=false; //用于兼容可能提前注入导致DOM未解析完更新的问题
  14. // H5 plus事件处理
  15. function plusReady(){
  16. // 获取音频目录对象
  17. plus.io.resolveLocalFileSystemURL('_doc/', function(entry){
  18. entry.getDirectory('audio', {create:true}, function(dir){
  19. gentry = dir;
  20. updateHistory();
  21. }, function(e){
  22. outSet('Get directory "audio" failed: '+e.message);
  23. });
  24. }, function(e){
  25. outSet('Resolve "_doc/" failed: '+e.message);
  26. } );
  27. }
  28. if(window.plus){
  29. plusReady();
  30. }else{
  31. document.addEventListener('plusready', plusReady, false);
  32. }
  33. // DOMContentLoaded事件处理
  34. document.addEventListener('DOMContentLoaded', function(){
  35. // 获取DOM元素对象
  36. hl = document.getElementById('history');
  37. le = document.getElementById('empty');
  38. er = document.getElementById('record');
  39. rt = document.getElementById('rtime');
  40. ep = document.getElementById('play');
  41. pt = document.getElementById('ptime');
  42. pp = document.getElementById('progress')
  43. ps = document.getElementById('schedule');
  44. updateHistory();
  45. },false);
  46. // 添加播放项
  47. function createItem( entry ) {
  48. var li = document.createElement('li');
  49. li.className = 'ditem';
  50. li.innerHTML = '<span class="iplay"><font class="aname"></font><br/><font class="ainf"></font></span>';
  51. li.setAttribute('onclick', 'playAudio(this)');
  52. hl.insertBefore(li, le.nextSibling);
  53. li.querySelector('.aname').innerText = entry.name;
  54. li.querySelector('.ainf').innerText = '...';
  55. li.entry = entry;
  56. updateInformation(li);
  57. // 设置空项不可见
  58. le.style.display = 'none';
  59. }
  60. // 开始录音
  61. var r=null,t=0,ri=null,rt=null;
  62. function startRecord(){
  63. outSet('开始录音:');
  64. r = plus.audio.getRecorder();
  65. if ( r == null ) {
  66. outLine('录音对象未获取');
  67. return;
  68. }
  69. r.record({filename:'_doc/audio/'}, function(p){
  70. outLine('录音完成:'+p);
  71. plus.io.resolveLocalFileSystemURL(p, function(entry){
  72. createItem(entry);
  73. }, function(e){
  74. outLine('读取录音文件错误:'+e.message);
  75. });
  76. }, function(e){
  77. outLine('录音失败:'+e.message);
  78. } );
  79. er.style.display = 'block';
  80. t = 0;
  81. ri = setInterval(function(){
  82. t++;
  83. rt.innerText = timeToStr(t);
  84. }, 1000);
  85. }
  86. // 停止录音
  87. function stopRecord(){
  88. er.style.display = 'none';
  89. rt.innerText = '00:00:00';
  90. clearInterval(ri);
  91. ri = null;
  92. r.stop();
  93. w = null;
  94. r = null;
  95. t = 0;
  96. }
  97. // 清除历史记录
  98. function cleanHistory(){
  99. hl.innerHTML = '<li id="empty" class="ditem-empty">无历史记录</li>';
  100. le = document.getElementById('empty');
  101. // 删除音频文件
  102. outSet('清空录音历史记录:');
  103. gentry.removeRecursively(function(){
  104. // Success
  105. outLine('操作成功!');
  106. }, function(e){
  107. ouline('操作失败:'+e.message);
  108. });
  109. }
  110. // 获取录音历史列表
  111. function updateHistory(){
  112. if(bUpdated||!gentry||!document.body){//兼容可能提前注入导致DOM未解析完更新的问题
  113. return;
  114. }
  115. var reader = gentry.createReader();
  116. reader.readEntries(function(entries){
  117. for(var i in entries){
  118. if(entries[i].isFile){
  119. createItem(entries[i]);
  120. }
  121. }
  122. }, function(e){
  123. outLine('读取录音列表失败:'+e.message);
  124. });
  125. bUpdated = true;
  126. }
  127. // 获取录音文件信息
  128. function updateInformation(li){
  129. if(!li || !li.entry){
  130. return;
  131. }
  132. var entry = li.entry;
  133. entry.getMetadata(function(metadata){
  134. li.querySelector('.ainf').innerText = dateToStr(metadata.modificationTime);
  135. }, function(e){
  136. outLine('获取文件"'+entry.name+'"信息失败:'+e.message);
  137. } );
  138. }
  139. // 播放音频文件
  140. function playAudio(li){
  141. if(!li || !li.entry){
  142. ouSet('无效的音频文件');
  143. return;
  144. }
  145. outSet('播放音频文件:'+li.entry.name);
  146. startPlay('_doc/audio/'+li.entry.name);
  147. }
  148. // 播放文件相关对象
  149. var p=null,pt=null,pp=null,ps=null,pi=null;
  150. // 开始播放
  151. function startPlay(url){
  152. ep.style.display = 'block';
  153. var L = pp.clientWidth;
  154. p = plus.audio.createPlayer(url);
  155. p.play(function(){
  156. outLine('播放完成!');
  157. // 播放完成
  158. pt.innerText = timeToStr(d)+'/'+timeToStr(d);
  159. ps.style.webkitTransition = 'all 0.3s linear';
  160. ps.style.width = L+'px';
  161. stopPlay();
  162. }, function(e){
  163. outLine('播放音频文件"'+url+'"失败:'+e.message);
  164. });
  165. // 获取总时长
  166. var d = p.getDuration();
  167. if(!d){
  168. pt.innerText = '00:00:00/'+timeToStr(d);
  169. }
  170. pi = setInterval(function(){
  171. if(!d){ // 兼容无法及时获取总时长的情况
  172. d = p.getDuration();
  173. }
  174. var c = p.getPosition();
  175. if(!c){ // 兼容无法及时获取当前播放位置的情况
  176. return;
  177. }
  178. pt.innerText = timeToStr(c)+'/'+timeToStr(d);
  179. var pct = Math.round(L*c/d);
  180. if(pct < 8){
  181. pct = 8;
  182. }
  183. ps.style.width = pct+'px';
  184. }, 1000);
  185. }
  186. // 停止播放
  187. function stopPlay(){
  188. clearInterval(pi);
  189. pi=null;
  190. setTimeout(resetPlay, 500);
  191. // 操作播放对象
  192. if(p){
  193. p.stop();
  194. p=null;
  195. }
  196. }
  197. // 重置播放页面内容
  198. function resetPlay(){
  199. ep.style.display = 'none';
  200. ps.style.width = '8px';
  201. ps.style.webkitTransition = 'all 1s linear';
  202. pt.innerText = '00:00:00/00:00:00';
  203. }
  204. // 重写关闭
  205. var _back=window.back;
  206. function resetback(){
  207. // 停止播放
  208. if(ep.style.display == 'block'){
  209. stopPlay();
  210. }else if(er.style.display == 'block'){
  211. stopRecord();
  212. }else{
  213. _back();
  214. }
  215. }
  216. window.back=resetback;
  217. </script>
  218. <link rel="stylesheet" href="../css/common.css" type="text/css" charset="utf-8"/>
  219. <style type="text/css">
  220. .rp {
  221. width: 100%;
  222. height: 100%;
  223. display: none;
  224. text-align: center;
  225. position: fixed;
  226. top: 0;
  227. background: rgba(0,0,0,0.8);
  228. z-index: 9999;
  229. overflow: hidden;
  230. }
  231. .aname {
  232. font-size: 16px;
  233. }
  234. .ainf {
  235. font-size: 12px;
  236. }
  237. .rtime {
  238. font-size: 22px;
  239. color: #FF0000;
  240. }
  241. .ptime {
  242. margin-top: 40%;
  243. font-size: 22px;
  244. color: #FFFFFF;
  245. }
  246. .rprogress {
  247. background: url(../img/arecord.png) no-repeat center center;
  248. background-size: 32px 32px;
  249. }
  250. .rschedule {
  251. background-color: rgba(0,0,0,0);
  252. border: 5px solid rgba(0,183,229,0.9);
  253. opacity: .9;
  254. border-left: 5px solid rgba(0,0,0,0);
  255. border-right: 5px solid rgba(0,0,0,0);
  256. border-radius: 50px;
  257. box-shadow: 0 0 15px #2187e7;
  258. width: 36px;
  259. height: 36px;
  260. margin: 0 auto;
  261. -webkit-animation: spin 1s infinite linear;
  262. animation: spin 1s infinite linear;
  263. }
  264. @-webkit-keyframes spin {
  265. 0% {
  266. -webkit-transform: rotate(0deg);
  267. }
  268. 100% {
  269. -webkit-transform: rotate(360deg);
  270. }
  271. }
  272. @keyframes spin {
  273. 0% {
  274. transform: rotate(0deg);
  275. }
  276. 100% {
  277. transform: rotate(360deg);
  278. }
  279. }
  280. .progress {
  281. width: 90%;
  282. background-color: #666;
  283. margin: 0 5%;
  284. border: 1px solid #222;
  285. -webkit-border-radius: 5px;
  286. border-radius: 5px;
  287. }
  288. .schedule {
  289. width: 8px;
  290. height: 8px;
  291. margin: 1px 0;
  292. background-color: #FFCC33;
  293. -webkit-border-radius: 4px;
  294. border-radius: 4px;
  295. -webkit-transition: all 1s linear;
  296. transition: all 1s linear;
  297. }
  298. .stop {
  299. width: 72px;
  300. height: 72px;
  301. background: url(../img/astop.png) center center;
  302. background-size: 72px 72px;
  303. margin: auto;
  304. -webkit-border-radius: 72px;
  305. border-radius: 72px;
  306. }
  307. .stop:active{
  308. -webkit-box-shadow: 0 3px 8px rgba(0, 0, 0, 0.5) inset;
  309. box-shadow: 0 3px 8px rgba(0, 0, 0, 0.5) inset;
  310. }
  311. .iplay {
  312. display: block;
  313. background: no-repeat right center url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABYCAYAAAADWlKCAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAKwwAACsMBNCkkqwAAABZ0RVh0Q3JlYXRpb24gVGltZQAwOS8xMi8xM5w+I3MAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzVxteM2AAAD9UlEQVR4nO2b3XETMRRGDwzvoYOkg5hRAVkqiKmAdIA7wHSQVECoALsC1gXciV0BTge4gvCwgnHk9d/+WF8m97ztxrlXs8fS1Urym6enJxwd3uZugPMcFyKGCxHDhYjhQsRwIWK4EDFciBguRAwXIoYLEcOFiOFCxHAhYrgQMVyIGC5EDBcihgsRw4WI4ULEcCFiuBAx3uVuwDGY2XtgCBTAALjc8tEFMAdKYBJC+HOK9nXBm5dwUM7MCmAEXDcMMQVuQwhlV23qC2khZjYAboGrjkLOgFEIYd5RvM6RrSFmdgs80J0MYqyHGFsSuR4S60TJ9vrwCEziZ+YhhGXy/xdU9aWgqjfnW+IsgEKtvkgJiUPUPfUyZsD42DoQ68+Y+p62AG6UhjAZITt6xopq3L9vGf+Gqh6dJX+S6ilKNaRkU8YCGLSVARBjDGLMdS5jbgkkhMQiWyejSGtEG2KsghopKoU++5AV68ZDcrvXYWTH8Pghdz1R6CHpN3MFDPsc02PsYcy1qy0nJ6uQOANKZz+jfcOUmd3H6W1jYo5RcvsqtikbuXtI+kBmBxbwz8DczMZtksdcsz1tOinZhMRxPF2bGh8R4gz4amZLMxu2aEqa8zq2LQs5e0j6EB8bLv6dAz/NrGwyjMWcj3vadjJyCimS60nLeFfAbzO7bfANT3MXLdvSmJxCBsl12VHcL8AyvpkfSpo7bdvJyCkkfQfocv5/Bnw3s/mBs6Y097aFzd7JPcv6T5dv5GtcAr/2TZN7yt0IGSE908k0+RS8FiEvhhd1yKEFUw5YAVBApoe0XQrZwgL4GEIY7pLRU+5G5OwhC57PZgbAsqPYK6rdxUMXC9Npbro8fzJy9pB0qll0FPcOuDhCRl3ubEvwOYWUyXXb5YoZ1X7GqMHSfZq7bNmWxuQUki5XnDdc+n4EPoUQiiabSzFnejKl7TJOY7IJid/iaXJ7fESIFfCNas+9zQNMc05zHnjIPctKx/mrA9egflCJGLd5eDFXukGWdddQYU+95PlDWVE97GXPeS+oivf6saBZCKHoM+8+cvcQ2NyhOwMmfW4SxdgTNs9oZd0tBAEhsRDfJbcvgbIPKTtOnNzlPnECAkPWP8xsTv3ZrJ1v2UfmuKDqGRt5QgjZ9kDWyd5D1iioP1U4P3KzqZYYY5v0om38rpDpIeCHrUFMCPjPEeSE/COetf3SU/i7EEL2GVUdSjXkGfGBfWDzIFsb/q93dRizU2R7yDr+o09R/GfRzsmRrSGvFRcihgsRw4WI4ULEcCFiuBAxXIgYLkQMFyKGCxHDhYjhQsRwIWK4EDFciBguRAwXIoYLEcOFiOFCxHAhYrgQMf4CVuqCm+17t3sAAAAASUVORK5CYII=);
  314. background-size: 50px 44px;
  315. -ms-touch-action: auto;
  316. }
  317. </style>
  318. </head>
  319. <body>
  320. <br/>
  321. <div class="button" onclick="startRecord()">开始录音</div>
  322. <div class="button" onclick="startPlay('_www/audio/alice.mp3')">播放音乐</div>
  323. <br/>
  324. <!-- History list -->
  325. <ul id="history" class="dlist" style="text-align:left;">
  326. <li id="empty" class="ditem-empty">无历史记录</li>
  327. </ul>
  328. <br/>
  329. <div class="button button-waring" onclick="cleanHistory()">清空历史记录</div>
  330. <br/>
  331. <div id="outpos"/>
  332. <div id="output">
  333. Audio用于管理音频设备,可调用麦克风录制音频文件,也可播放音频文件。
  334. </div>
  335. <div id="play" class="rp">
  336. <div id="ptime" class="ptime">00:00:00/00:00:00</div><br/>
  337. <div id="progress" class="progress"><div id="schedule" class="schedule"></div></div>
  338. <br/>
  339. <div class="stop" onclick="stopPlay(),outSet('停止播放!')"></div>
  340. </div>
  341. <div id="record" class="rp">
  342. <div style="width:100%;height:20%;"></div>
  343. <div class="rprogress"><div class="rschedule"></div></div>
  344. <br/>
  345. <div id="rtime" class="rtime">00:00:00</div><br/>
  346. <div class="stop" onclick="stopRecord()"></div>
  347. </div>
  348. </body>
  349. </html>