audio.min.1.0.4.js 6.7 KB

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