Audio.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. module.exports = (option) => {
  2. option = option || {};
  3. const app = option.app;
  4. class Audio {
  5. constructor(option) {
  6. const _ts = this;
  7. _ts.option = option.option;
  8. _ts.playerId = option.playerId;
  9. _ts.dataId = option.dataId;
  10. this.player = this.createPlayer();
  11. this.status = 'init';
  12. }
  13. // 播放
  14. play() {
  15. const _ts = this;
  16. _ts.player.play();
  17. }
  18. // 暂停
  19. pause() {
  20. const _ts = this;
  21. _ts.player.pause();
  22. }
  23. // 获取需要更新的数据键名
  24. getAppDataKey(id){
  25. for(let key in app.data){
  26. let item = app.data[key];
  27. if(item.id === id){
  28. return key;
  29. };
  30. };
  31. }
  32. updateView(data){
  33. data = data || {};
  34. const _ts = this,
  35. option = _ts.option;
  36. _ts.updateKey = _ts.updateKey || _ts.getAppDataKey(_ts.dataId)
  37. let articleData = global.__towxmldata__[_ts.dataId].article,
  38. playerData = global.__towxmldata__[_ts.dataId].audio[_ts.playerId];
  39. // 检查如果数据没有被应用到页面上则中止操作
  40. if(!_ts.updateKey){
  41. return;
  42. };
  43. // 将选项和新传入的数据组合到viewData,后续更新使用
  44. for(let key in data){
  45. option[key] = data[key];
  46. };
  47. // 设置默认进的播放进度
  48. option.duration = _ts.duration || 0.001;
  49. option.currentTime = _ts.currentTime || 0;
  50. option.class = option.class || 'audioForH2w';
  51. // 设置播放器样式
  52. playerData.attr.class = option.class;
  53. // 设置封面图片
  54. playerData.child[1].child[0].attr.src = option.poster;
  55. // 设置进度条
  56. playerData.child[2].child[0].attr.style = `width:${option.currentTime / option.duration * 100}%`;
  57. // 设置title、歌手、播放时间
  58. playerData.child[2].child[1].child[0].text = option.name;
  59. playerData.child[2].child[2].child[0].text = option.author;
  60. playerData.child[2].child[3].child[0].text = `${_ts.formatTime(option.duration)} / ${_ts.formatTime(option.currentTime)}`;
  61. // 更新数据
  62. let updateData = {};
  63. updateData[_ts.updateKey] = articleData;
  64. app.setData(updateData);
  65. }
  66. // 创建播放器
  67. createPlayer() {
  68. const _ts = this;
  69. let option = _ts.option,
  70. autoplay = option.autoplay === 'true' ? true :
  71. option.autoplay === 'false' ? false :
  72. !!option.autoplay,
  73. loop = option.loop === 'true' ? true :
  74. option.loop === 'false' ? false :
  75. !!option.loop,
  76. src = option.src,
  77. audio = wx.createInnerAudioContext();
  78. audio.autoplay = autoplay;
  79. audio.loop = loop;
  80. audio.src = src;
  81. // 进入可播放状态时更新视图
  82. audio.onCanplay(() =>{
  83. _ts.updateView({
  84. class:'audioForH2w'
  85. });
  86. });
  87. // 播放
  88. audio.onPlay(() => {
  89. _ts.status = 'start';
  90. _ts.updateView({
  91. class:'audioForH2w audioForH2w--play'
  92. });
  93. });
  94. // 播放过程中
  95. let temp = 0;
  96. audio.onTimeUpdate(function (obj) {
  97. _ts.status = 'update';
  98. _ts.duration = audio.duration;
  99. _ts.currentTime = audio.currentTime;
  100. // 每5秒更新一次(否则内容过多会导致性能低下)
  101. if(_ts.currentTime - temp > 5){
  102. temp = _ts.currentTime;
  103. _ts.updateView({
  104. class:'audioForH2w audioForH2w--play'
  105. });
  106. };
  107. });
  108. // 暂停
  109. audio.onPause(obj => {
  110. _ts.status = 'pause';
  111. _ts.updateView({
  112. class:'audioForH2w'
  113. });
  114. });
  115. // 停止
  116. audio.onEnded(obj => {
  117. _ts.status = 'end';
  118. _ts.updateView({
  119. class:'audioForH2w audioForH2w--end'
  120. });
  121. });
  122. return audio;
  123. }
  124. // 数字补位
  125. fillIn = val => {
  126. return `${val < 10 ? '0' : ''}${val}`;
  127. }
  128. // 格式化时间
  129. formatTime = time => {
  130. let fillIn = this.fillIn,
  131. second = Math.floor(time % 60),
  132. minute = Math.floor(time / 60 % 60),
  133. hour = Math.floor(time / 60 / 60);
  134. return `${fillIn(hour)}:${fillIn(minute)}:${fillIn(second)}`;
  135. }
  136. };
  137. return new Audio(option);
  138. };