Music.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. Namespace.register("U.MT.UI.music");
  2. /**
  3. * [Control description] 音乐控件总函数
  4. * @param {[type]} musicList [数组json 格式请看文档]
  5. * @param {[type]} index [需要播放第几首歌(索引)]
  6. * @param {[type]} autoplay [是否自动播放]
  7. */
  8. U.MT.UI.Music = function (musicList, index, autoplay) {
  9. var _music = U.MT.UI.Music; //简写命名空间
  10. U.selectEl("body").addClass("U_MT_UI_Music_bodyClass");
  11. if (_musicBox = U.selectEl("#U_MT_UI_Music_musicBox")[0]) { //如若html代码存在 因此可以返回 防止重复添加
  12. U.selectEl(_musicBox).removeClass('U_MT_UI_Music_hidden');
  13. var _attr = _music.Attr; //简写全局属性json名
  14. var _audio = U.selectEl("#U_MT_UI_Music_audio"); //audio标签
  15. _attr.musicList = musicList; //全局赋值a
  16. _attr.musicIndex = index; //全局赋值
  17. _audio[0].src = musicList[index].src; //添加音乐路径
  18. var _Name = U.selectEl("#U_MT_UI_Music_Name"); //音乐名字节点
  19. _Name[0].innerText = musicList[index].title; //音乐名字赋值
  20. //$(_musicBox).removeClass('U_MT_UI_Music_hidden');
  21. return;
  22. }
  23. _music.create(); //创建音乐控件
  24. _music.Attr = { //全局属性
  25. musicIndex: index, //当前数据索引
  26. musicList: musicList, //所有数据
  27. autoplay: autoplay, //第一首是否自动播放
  28. currentTime: null, //音乐当前时间未赋值
  29. endTime: null //音乐结束时间未赋值
  30. };
  31. _music.init(); //初始化函数
  32. };
  33. U.MT.UI.Music.Attr = null; //存放元素与变量的json全局变量 未赋值
  34. U.MT.UI.Music.htmlTemplte = '<div class="U_MT_UI_Music_soundBox" id="U_MT_UI_Music_soundBox"> <!-- 声音盒子 -->\n' +
  35. ' <div class="U_MT_UI_Music_closeBtn" id="U_MT_UI_Music_closeBtn"></div> <!-- 声音关闭图标 -->\n' +
  36. ' <div class="U_MT_UI_Music_soundSwitch" id="U_MT_UI_Music_soundSwitch"></div> <!-- 声音开关图标 -->\n' +
  37. ' <div class="U_MT_UI_Music_soundBar" id="U_MT_UI_Music_soundBar"></div> <!-- 声音条 -->\n' +
  38. ' <div class="U_MT_UI_Music_soundBall" id="U_MT_UI_Music_soundBall"></div> <!-- 声音球 -->\n' +
  39. ' </div>\n' +
  40. ' <p class="U_MT_UI_Music_Name" id="U_MT_UI_Music_Name">Welocme</p> <!-- 音乐歌曲名 -->\n' +
  41. ' <div class="U_MT_UI_Music_CoverBox">\n' +
  42. ' <img src="/img/Controls/Audio/moblie/Music.png" alt="" id="U_MT_UI_Music_Cover">\n' +
  43. ' </div> <!-- 图片封面 -->\n' +
  44. ' <div class="U_MT_UI_Music_buttonBox">\n' +
  45. ' <div class="U_MT_UI_Music_leftBtn" id="U_MT_UI_Music_leftBtn"></div> <!-- 上一首按钮 -->\n' +
  46. ' <div class="U_MT_UI_Music_playBtnBox">\n' +
  47. ' <div class="U_MT_UI_Music_pauseBtn U_MT_UI_Music_playBtn" id="U_MT_UI_Music_playBtn"></div> <!-- 开始/暂停按钮 -->\n' +
  48. ' </div>\n' +
  49. ' <div class="U_MT_UI_Music_rightBtn" id="U_MT_UI_Music_rightBtn"></div> <!-- 下一首按钮 -->\n' +
  50. ' <div class="U_MT_UI_Music_listBtn" id="U_MT_UI_Music_listBtn"></div> <!-- 清单按钮 -->\n' +
  51. ' </div>\n' +
  52. ' <div class="U_MT_UI_Music_progressBox" id="U_MT_UI_Music_progressBox">\n' +
  53. ' <div class="U_MT_UI_Music_currentTime" id="U_MT_UI_Music_currentTime">00:00</div> <!-- 开始时间 -->\n' +
  54. ' <div class="U_MT_UI_Music_progressBar" id="U_MT_UI_Music_progressBar"></div> <!-- 时间条 -->\n' +
  55. ' <div class="U_MT_UI_Music_progressBall" id="U_MT_UI_Music_progressBall"></div> <!-- 时间球 -->\n' +
  56. ' <div class="U_MT_UI_Music_endTime" id="U_MT_UI_Music_endTime">00:00</div> <!-- 结束时间 -->\n' +
  57. ' </div>\n' +
  58. ' <audio src="" id="U_MT_UI_Music_audio" autoplay ></audio>';
  59. /**
  60. * 添加音乐控件html代码 并且判断是否存在html 防止多次添加
  61. */
  62. U.MT.UI.Music.create = function () {
  63. var _musicBox = $$("div", { id: 'U_MT_UI_Music_musicBox', className: 'U_MT_UI_Music_musicBox' }, document.body);
  64. _musicBox.innerHTML += U.MT.UI.Music.htmlTemplte;
  65. };
  66. /**
  67. * 音乐控件初始化
  68. */
  69. U.MT.UI.Music.init = function () {
  70. var _music = U.MT.UI.Music; //简写命名空间
  71. var _attr = _music.Attr; //简写全局属性
  72. var _audio = U.selectEl("#U_MT_UI_Music_audio"); //audio标签
  73. var _playBtn = U.selectEl("#U_MT_UI_Music_playBtn"); //暂停播放按钮
  74. var _Name = U.selectEl("#U_MT_UI_Music_Name"); //音乐名字
  75. var _musicList = _attr.musicList; //音乐列表数组
  76. var _musicIndex = _attr.musicIndex; //需要播放的音乐(数组中的第index个)
  77. _audio[0].src = _musicList[_musicIndex].src; //添加音乐路径
  78. var _corver = U.selectEl("#U_MT_UI_Music_Cover"); //封面图片节点
  79. var _endTimeBox = U.selectEl("#U_MT_UI_Music_endTime"); //结束时间 盒子节点
  80. if (!_attr.autoplay) { //若autoplay属性 = false 则第一首音乐暂停
  81. _audio[0].pause();
  82. }
  83. _music.soundControl(); //声音控制器
  84. _music.playEvent(); //音乐播放与暂停控制器
  85. _music.switchMusic(); //切换音乐按钮
  86. _music.progressControl(); //音乐进度条控制器
  87. _audio.bind("durationchange", function () { //当音乐时长已改变时 给节点赋值
  88. _attr.endTime = this.duration; //总时长赋值
  89. _endTimeBox[0].innerText = _music.secondToDate(_attr.endTime); //结束时间节点 内容转为 分:秒
  90. _musicIndex = _attr.musicIndex; //音乐索引位置重赋值
  91. _Name[0].innerText = _musicList[_musicIndex].title; //音乐名字赋值
  92. //_corver.src = _musicList[_musicIndex].cover; //音乐封面图片赋值
  93. });
  94. _audio.bind("ended", function () { //音乐结束后切换下一首
  95. _musicIndex = _attr.musicIndex; //由于_attr.musicIndex是一个变量 因此 需要重新赋值
  96. var _listLength = _musicList.length - 1; //获取数组中音乐的长度
  97. if (_musicIndex === _listLength) { //当音乐在数组中为最后一首时 下一首则为第一首 也就是索引 0
  98. _attr.musicIndex = 0;
  99. _musicIndex = _attr.musicIndex;
  100. _audio[0].src = _musicList[_musicIndex].src;
  101. } else { //否则则索引+1
  102. _attr.musicIndex++;
  103. _musicIndex = _attr.musicIndex;
  104. _audio[0].src = _musicList[_musicIndex].src;
  105. }
  106. });
  107. };
  108. /**
  109. * 播放/暂停 的点击事件 与 关闭音乐的点击事件
  110. */
  111. U.MT.UI.Music.playEvent = function () { // 播放/暂停 的点击事件
  112. var _music = U.MT.UI.Music; //简写命名空间
  113. var _attr = _music.Attr; //简写全局属性
  114. var _playBtn = U.selectEl("#U_MT_UI_Music_playBtn"); //暂停/播放 按钮
  115. var _audio = U.selectEl("#U_MT_UI_Music_audio"); //audio标签
  116. var _closeBtn = U.selectEl("#U_MT_UI_Music_closeBtn");
  117. _playBtn.bind('click', function () {
  118. if (!_audio[0].paused) { //如在 无暂停状态(播放状态)
  119. _playBtn.addClass('U_MT_UI_Music_playBtn'); //暂停音乐并修改图标
  120. _audio[0].pause();
  121. } else { //否则则时 暂停状态时
  122. _playBtn.removeClass('U_MT_UI_Music_playBten');
  123. _audio[0].play(); //播放音乐并修改图标
  124. }
  125. });
  126. _closeBtn.bind('click', function (e) {
  127. U.selectEl("#U_MT_UI_Music_musicBox").addClass("U_MT_UI_Music_hidden"); //点击关闭按钮后 隐藏音乐控件
  128. U.selectEl("body").removeClass("U_MT_UI_Music_bodyClass");
  129. });
  130. _closeBtn.bind('touchstart', function (e) {
  131. U.UF.EV.stopBubble(e); //阻止冒泡 音量球的点击效果
  132. });
  133. };
  134. /**
  135. * 声音事件控制 总函数
  136. */
  137. U.MT.UI.Music.soundControl = function () {
  138. var _music = U.MT.UI.Music; //简写命名空间
  139. var _attr = _music.Attr; //简写全局属性
  140. var _audio = U.selectEl("#U_MT_UI_Music_audio"); //audio标签
  141. var _soundBox = U.selectEl("#U_MT_UI_Music_soundBox"); //声音盒子节点
  142. var _soundBall = U.selectEl("#U_MT_UI_Music_soundBall"); //音量球
  143. var _soundBar = U.selectEl("#U_MT_UI_Music_soundBar"); //声音条
  144. var _boxWidth = _soundBox[0].clientWidth; //获取盒子宽度 = 声音球位置的最大值
  145. var _volume = 0.5; //声音初始大小
  146. _audio[0].volume = _volume; //给audio标签添加声音
  147. _soundBall[0].style.left = (_boxWidth * _volume) + "px"; //调整音量球位置 = 总宽度*百分比
  148. _soundBar[0].style.width = (_boxWidth * _volume) + "px"; //调整声音条宽度 = 总宽度*百分比
  149. _soundBox.bind('touchstart', function (e) { //点击进度条后 音量球跳转到鼠标点击位置 并且声音跟随增大或减小
  150. var _boxLeft = _music.getOffsetLeft(this); //body距离盒子左端的left值 = 声音球left的最小值
  151. var _boxRight = _boxLeft + _boxWidth; //body距离盒子右端的left值 = 声音球left的最大值
  152. var _mouseX = e.targetTouches[0].clientX; //获取鼠标按下时的X坐标
  153. _mouseX = Math.max(_mouseX, _boxLeft); //mouseX 与 boxLeft距离不能小于0 因此 获取两数最大值 原因:声音不能小于0
  154. _mouseX = Math.min(_mouseX, _boxRight); //mouseX 与 boxRight因此 获取两数最大值 原因:声音不能大于1
  155. var _dis = _mouseX - _boxLeft; //鼠标划过的距离
  156. _volume = Math.round(parseFloat(_dis / _boxWidth) * 100) / 100; //距离相对于盒子宽度的值 = 声音百分比大小(此处为保留两位小数点)
  157. _soundBall[0].style.left = (_boxWidth * _volume) + "px"; //音量球left值 改变成 = 总宽*百分比
  158. _soundBar[0].style.width = (_boxWidth * _volume) + "px"; //音量条width 改变成 = 总宽*百分比
  159. _audio[0].volume = _volume; //改变audio标签值
  160. });
  161. _soundBall.bind('touchstart', function (e) { //音量球拖拽效果
  162. U.UF.EV.stopBubble(e); //阻止冒泡 防止被document事件覆盖
  163. var _oMouseX = e.targetTouches[0].clientX; //获取鼠标按下时的X坐标
  164. var _soundDrapMove = function (e) { //拖拽时移动用的函数
  165. U.UF.EV.stopBubble(e); //阻止冒泡 防止被document事件覆盖
  166. U.UF.EV.stopDefault(e); //取消默认拖拽
  167. var _mouseX = e.targetTouches[0].clientX; //鼠标移动时的x坐标
  168. var _dis = _mouseX - _oMouseX + _oX; //移动的距离
  169. _dis = Math.max(0, _dis); //限制音量球left不得小于0
  170. _dis = Math.min(_boxWidth, _dis); //限制音量球left不得大于盒子宽度
  171. _soundBall[0].style.left = _dis + "px"; //音量球位置
  172. _soundBar[0].style.width = _dis + "px"; //音量条宽度
  173. _volume = Math.round(parseFloat(_dis / _boxWidth) * 100) / 100; //声音球距离盒子宽度的left值 = 声音百分比大小(此处为保留两位小数点)
  174. _audio[0].volume = _volume; //音乐的声音赋值
  175. };
  176. var _soundDragUp = function () { //拖拽时松开用的函数
  177. _soundBall.unbind('touchmove', _soundDrapMove); //删除move监听事件
  178. _soundBall.unbind('touchend', _soundDragUp); //删除end监听事件
  179. };
  180. var _oX = parseFloat(_soundBall.css("left")); //获取鼠标按下时音量球的坐标
  181. _soundBall.bind('touchmove', _soundDrapMove);
  182. _soundBall.bind('touchend', _soundDragUp);
  183. });
  184. };
  185. /**
  186. * 进度条控制 事件总函数
  187. */
  188. U.MT.UI.Music.progressControl = function () {
  189. var _music = U.MT.UI.Music; //简写命名空间
  190. var _attr = _music.Attr; //简写全局属性
  191. var _audio = U.selectEl("#U_MT_UI_Music_audio"); //audio标签
  192. var _progressBox = U.selectEl("#U_MT_UI_Music_progressBox"); //时间盒子节点
  193. var _progressBall = U.selectEl("#U_MT_UI_Music_progressBall"); //时间球
  194. var _progressBar = U.selectEl("#U_MT_UI_Music_progressBar"); //时间条
  195. var _playBtn = U.selectEl("#U_MT_UI_Music_playBtn"); //播放/暂停 按钮
  196. var _boxWidth = _progressBox[0].clientWidth; //时间盒子宽度 = 时间球位置的最大值
  197. var _barFlag = true, _currentTime; //声明两个全局变量 为更新时间条所用
  198. var _currentTimeBox = U.selectEl("#U_MT_UI_Music_currentTime"); //开始时间 盒子节点
  199. var _endTimeBox = U.selectEl("#U_MT_UI_Music_endTime"); //结束时间 盒子节点
  200. _audio.bind('timeupdate', function () {
  201. if (!this.paused) { //如在 无暂停状态(播放状态)
  202. _playBtn.removeClass('U_MT_UI_Music_playBtn'); //修改成 播放时用的图标
  203. } else { //否则 为暂停状态
  204. _playBtn.addClass('U_MT_UI_Music_playBtn'); //修改成暂停用的图标
  205. }
  206. if (_barFlag) { //barFlag = true 为 时间球不在拖拽状态时
  207. _currentTime = this.currentTime; //获取音乐当前播放时间
  208. _currentTimeBox[0].innerText = _music.secondToDate(_currentTime); //当前时间节点内容 = 分:秒
  209. var _speed = Math.round(parseFloat(_currentTime / _attr.endTime) * 10000) / 10000; //_speed = 当前时间相对于总时长的 百分比
  210. _progressBall[0].style.left = (_boxWidth * _speed) + "px"; //时间球的left = _speed(百分比)*总宽度
  211. _progressBar[0].style.width = (_boxWidth * _speed) + "px"; //时间条的width = _speed(百分比)*总宽度
  212. }
  213. });
  214. _progressBox.bind('touchstart', function (e) { //点击进度条后 时间球跳转到鼠标点击位置 时间跟随改变
  215. var _boxLeft = _music.getOffsetLeft(this); //body距离盒子左端的left值 = 时间球left的最小值
  216. var _boxRight = _boxLeft + _boxWidth; //body距离盒子右端的left值 = 时间球left的最大值
  217. var _mouseX = e.targetTouches[0].clientX; //获取鼠标按下时的X坐标
  218. _mouseX = Math.max(_mouseX, _boxLeft); //mouseX 与 boxLeft距离不能小于0 因此 获取两数最大值 原因:声音不能小于0
  219. _mouseX = Math.min(_mouseX, _boxRight); //mouseX 与 boxRight因此 获取两数最大值 原因:声音不能大于1
  220. var _dis = _mouseX - _boxLeft; //鼠标划过的距离
  221. _speed = Math.round(parseFloat(_dis / _boxWidth) * 10000) / 10000; //时间球距离盒子宽度的left值 = 时间当前值/总时长(此处为保留4位小数点)
  222. _audio[0].currentTime = _attr.endTime * _speed; //更新音乐当前时间 下一步执行 timeupdate里的函数
  223. });
  224. _progressBall.bind('touchstart', function (e) { //时间球拖拽效果
  225. U.UF.EV.stopBubble(e); //阻止冒泡
  226. _barFlag = false; //拖拽时 时间球跟随声音播放向前移动状态暂时屏蔽 详细见 timeupdate监听
  227. var _oMouseX = e.targetTouches[0].clientX; //获取鼠标按下时的X坐标
  228. var _progressDrapMove = function (e) {
  229. U.UF.EV.stopBubble(e); //阻止冒泡
  230. U.UF.EV.stopDefault(e); //取消默认拖拽
  231. var _mouseX = e.targetTouches[0].clientX; //鼠标移动时的x坐标
  232. var _dis = _mouseX - _oMouseX + _oX; //移动的距离
  233. _dis = Math.max(0, _dis); //限制音量球left不得小于0
  234. _dis = Math.min(_boxWidth, _dis); //限制音量球left不得大于盒子宽度
  235. _progressBall[0].style.left = _dis + "px"; //音量球位置
  236. _progressBar[0].style.width = _dis + "px"; //音量条宽度
  237. _speed = Math.round(parseFloat(_dis / _boxWidth) * 10000) / 10000; //时间球距离盒子宽度的left值 = 时间当前值/总时长(此处为保留4位小数点)
  238. _progressBall[0].style.left = (_boxWidth * _speed) + "px"; //时间球的left = 总宽*百分比
  239. _progressBar[0].style.width = (_boxWidth * _speed) + "px"; //时间条的width = 总宽*百分比
  240. _currentTime = _attr.endTime * _speed; //当前时间 = 音乐总时长*百分比
  241. _currentTimeBox[0].innerText = _music.secondToDate(_currentTime); //当前时间节点内容 = 分:秒
  242. };
  243. var _progressDragUp = function (e) {
  244. _audio[0].currentTime = _currentTime; //当前时间重新赋值
  245. _barFlag = true; //拖拽后松开时 时间球跟随声音播放向前移动
  246. _progressBall.unbind('touchmove', _progressDrapMove); //删除 touchmove的监听事件
  247. _progressBall.unbind('touchend', _progressDragUp); //删除touchend的监听事件
  248. };
  249. var _oX = parseFloat(_progressBall.css("left")); //获取鼠标按下时音量球的坐标
  250. _progressBall.bind('touchmove', _progressDrapMove);
  251. _progressBall.bind('touchend', _progressDragUp)
  252. });
  253. };
  254. /**
  255. * 音乐按钮切换(上一首 下一首)
  256. */
  257. U.MT.UI.Music.switchMusic = function () { //声音按钮切换
  258. var _music = U.MT.UI.Music; //简写命名空间
  259. var _attr = _music.Attr; //简写全局属性
  260. var _audio = U.selectEl("#U_MT_UI_Music_audio"); //audio标签
  261. var _rightBtn = U.selectEl("#U_MT_UI_Music_rightBtn"); //获取下一首的按钮
  262. var _leftBtn = U.selectEl("#U_MT_UI_Music_leftBtn"); //获取上一首的按钮
  263. var _musicList = _attr.musicList; //获取音乐数组数据
  264. var _musicIndex = _attr.musicIndex; //获取当前需要播放音乐 的数组索引
  265. var _listLength = _musicList.length - 1; //获取音乐的数量
  266. _rightBtn.bind('click', function () { //当点击右边(下一首)的按钮时
  267. _musicIndex = _attr.musicIndex; //由于_attr.musicIndex是一个变量 因此 需要重新赋值
  268. if (_musicIndex === _listLength) { //如果当前的歌曲是最后一首时
  269. _attr.musicIndex = 0; //则条转到第一首歌
  270. _musicIndex = _attr.musicIndex; //给全局属性赋值
  271. _audio[0].src = _musicList[_musicIndex].src; //并修改音乐路径
  272. } else { //否则跳转到下一首歌
  273. _attr.musicIndex++; //数组索引加1
  274. _musicIndex = _attr.musicIndex; //给全局属性赋值
  275. _audio[0].src = _musicList[_musicIndex].src; //并修改音乐路径
  276. }
  277. });
  278. _leftBtn.bind('click', function () { //同上 此处是左按钮(上一首)
  279. _musicIndex = _attr.musicIndex; //由于_attr.musicIndex是一个变量 因此 需要重新赋值
  280. if (_musicIndex === 0) {
  281. _attr.musicIndex = _listLength;
  282. _musicIndex = _attr.musicIndex;
  283. _audio[0].src = _musicList[_musicIndex].src;
  284. } else {
  285. _attr.musicIndex--;
  286. _musicIndex = _attr.musicIndex;
  287. _audio[0].src = _musicList[_musicIndex].src;
  288. }
  289. });
  290. };
  291. U.MT.UI.Music.getOffsetLeft = function (obj) {
  292. var tmp = obj.offsetLeft;
  293. var val = obj.offsetParent;
  294. while (val != null) {
  295. tmp += val.offsetLeft;
  296. val = val.offsetParent;
  297. }
  298. return tmp;
  299. };
  300. U.MT.UI.Music.secondToDate = function (result) {
  301. var m = Math.floor((result / 60 % 60));
  302. var s = Math.floor((result % 60));
  303. if (m < 10) {
  304. m = "0" + m;
  305. }
  306. if (s < 10) {
  307. s = "0" + s;
  308. }
  309. return result = m + ":" + s;
  310. };