audio.min.1.0.4.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * $(selector).initAudioPlayer();
  3. * 不支持自动播放-想了下,用播放器样式的一般都不自动播放,影响用户体验。一般要自动播放的都不需要进度条之类的,需要一个切换按钮即可。
  4. * 不支持audio的浏览器直接return
  5. */
  6. (function ($, window, document) {
  7. // 播放器样式 - 替换到css更改样式即可
  8. var onMobile = 'ontouchstart' in window,
  9. eStart = onMobile ? 'touchstart' : 'mousedown',
  10. eMove = onMobile ? 'touchmove' : 'mousemove',
  11. eCancel = onMobile ? 'touchcancel' : 'mouseup',
  12. hackPrefixes = ['webkit', 'moz', 'ms', 'o'],
  13. hackHiddenProperty = getHackHidden();
  14. $.fn.initAudioPlayer = function () {
  15. // 遍历处理audio
  16. this.each(function () {
  17. if ($(this).prop('tagName').toLowerCase() !== 'audio') {
  18. return;
  19. }
  20. var $this = $(this),
  21. file = $this.attr('src'),
  22. isSupport = false;
  23. if (canFilePlay(file)) {
  24. isSupport = true;
  25. } else {
  26. $this.find('source').each(function () {
  27. if (canFilePlay($(this).attr('src'))) {
  28. isSupport = true;
  29. return false;
  30. }
  31. });
  32. }
  33. if (!isSupport) {
  34. return;
  35. }
  36. // 添加播放器盒子
  37. var $player = $('<div class="ppq-audio-player">' + $('<div>').append($this.eq(0).clone()).html() + '<div class="play-pause-btn"><a href="javascript: void(0);" class="play-pause-icon"></a></div></div>'),
  38. audioEle = $player.find('audio')[0];
  39. $player.find('audio').addClass('audio-hidden');
  40. $player.append('<div class="player-time player-time-current"></div>\
  41. <div class="player-time player-time-duration"></div>\
  42. <div class="player-bar">\
  43. <div class="player-bar-loaded"></div>\
  44. <div class="player-bar-played"></div>\
  45. </div>');
  46. var $bar = $player.find('.player-bar'),
  47. $played = $player.find('.player-bar-played'),
  48. $loaded = $player.find('.player-bar-loaded'),
  49. $current = $player.find('.player-time-current'),
  50. $duration = $player.find('.player-time-duration');
  51. $current.html('00:00');
  52. $duration.html('&hellip;');
  53. initAudioEvents();
  54. bindPageEvents();
  55. $this.replaceWith($player);
  56. function initAudioEvents() {
  57. // 监听loadeddata,渲染进度条和时间
  58. audioEle.addEventListener('loadeddata', function () {
  59. var loadTimer = setInterval(function () {
  60. if (audioEle.buffered.length < 1) {
  61. return true;
  62. }
  63. $loaded.width((audioEle.buffered.end(0) / audioEle.duration) * 100 + '%');
  64. if (Math.floor(audioEle.buffered.end(0)) >= Math.floor(audioEle.duration)) {
  65. clearInterval(loadTimer);
  66. }
  67. }, 100);
  68. $duration.html($.isNumeric(audioEle.duration) ? convertTimeStr(audioEle.duration) : '&hellip;');
  69. });
  70. // 监听timeupdate,更新时间和进度条
  71. audioEle.addEventListener('timeupdate', function () {
  72. $current.html(convertTimeStr(audioEle.currentTime));
  73. $played.width((audioEle.currentTime / audioEle.duration) * 100 + '%');
  74. });
  75. // 监听ended,播放完恢复暂停状态
  76. audioEle.addEventListener('ended', function () {
  77. $player.removeClass('player-playing').addClass('player-paused');
  78. });
  79. audioEle.addEventListener('pause', function () {
  80. $player.removeClass('player-playing').addClass('player-paused');
  81. });
  82. }
  83. function bindPageEvents() {
  84. // 监听进度条touch,更新进度条和播放进度
  85. $bar.on(eStart, function (e) {
  86. audioEle.currentTime = getCurrentTime(e);
  87. $bar.on(eMove, function (e) {
  88. audioEle.currentTime = getCurrentTime(e);
  89. });
  90. }).on(eCancel, function () {
  91. $bar.unbind(eMove);
  92. });
  93. // 监听播放暂停按钮click
  94. $player.find('.play-pause-btn').on('click', function () {
  95. Array.from($("video")).forEach((item) => {
  96. if (!item.paused) {
  97. item.pause();
  98. }
  99. });
  100. Array.from($("audio")).forEach((item) => {
  101. if (!item.paused) {
  102. item.pause();
  103. }
  104. });
  105. if ($player.hasClass('player-playing')) {
  106. $player.removeClass('player-playing').addClass('player-paused');
  107. audioEle.pause();
  108. } else {
  109. $player.addClass('player-playing').removeClass('player-paused');
  110. audioEle.play();
  111. }
  112. return false;
  113. });
  114. }
  115. function getCurrentTime(e) {
  116. var et = onMobile ? e.originalEvent.touches[0] : e;
  117. return Math.round((audioEle.duration * (et.pageX - $bar.offset().left)) / $bar.width());
  118. }
  119. if (hackHiddenProperty) {
  120. var evtname = hackHiddenProperty.replace(/[H|h]idden/, '') + 'visibilitychange';
  121. document.addEventListener(evtname, function () {
  122. if (isHidden() || getHackVisibilityState() === 'hidden') {
  123. $player.removeClass('player-playing').addClass('player-paused');
  124. audioEle.pause();
  125. }
  126. }, false);
  127. }
  128. window.addEventListener('beforeunload', function () {
  129. $player.removeClass('player-playing').addClass('player-paused');
  130. audioEle.pause();
  131. }, false);
  132. });
  133. return this;
  134. }
  135. // 秒转为时间字符串
  136. function convertTimeStr(secs) {
  137. var m = Math.floor(secs / 60),
  138. s = Math.floor(secs - m * 60);
  139. return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
  140. }
  141. // 判断文件能不能播放
  142. function canFilePlay(file) {
  143. if (!file) {
  144. return false;
  145. }
  146. var media = document.createElement('audio');
  147. if (typeof media.canPlayType !== 'function') {
  148. return false;
  149. }
  150. var res = media.canPlayType('audio/' + file.split('.').pop().toLowerCase());
  151. return res === 'probably' || res === 'maybe';
  152. }
  153. function getHackHidden() {
  154. if ('hidden' in document) {
  155. return 'hidden';
  156. }
  157. for (var i = 0; i < hackPrefixes.length; i++) {
  158. if ((hackPrefixes[i] + 'Hidden') in document) {
  159. return hackPrefixes[i] + 'Hidden';
  160. }
  161. }
  162. return null;
  163. }
  164. function getHackVisibilityState() {
  165. if ('visibilityState' in document) {
  166. return 'visibilityState';
  167. }
  168. for (var i = 0; i < hackPrefixes.length; i++) {
  169. if ((hackPrefixes[i] + 'VisibilityState') in document) {
  170. return hackPrefixes[i] + 'VisibilityState';
  171. }
  172. }
  173. return null;
  174. }
  175. function isHidden() {
  176. var hide = getHackHidden();
  177. if (!hide) {
  178. return false;
  179. }
  180. return document[hide];
  181. }
  182. })(jQuery, window, document);