x-audio-play.vue 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <template>
  2. <view v-if='url' class='xpj-audio-box'>
  3. <view @click='startPlay' v-if="showImg">
  4. <image :src="startImg" v-show='!status' class="voice_icon"></image>
  5. <image :src="pauseImg" v-show='status' class="voice_icon"></image>
  6. </view>
  7. <view class="flexB voice">
  8. <view class='current-time time-text' :style="{color:textColor}">{{format(currentTime)}}</view>
  9. <view class='audio-action'>
  10. <slider @change='changeAudio' :activeColor="activeColor" :block-color="blockColor"
  11. :backgroundColor="backgroundColor" block-size="12" :disabled="currentTime==0" :min='0'
  12. :max='duration.toFixed(0)' :value='currentTime.toFixed(0)' :step='0.1'>
  13. </slider>
  14. </view>
  15. <view class='duration-time time-text' :style="{color:textColor}">{{format(duration)}}</view>
  16. </view>
  17. </view>
  18. </template>
  19. <script>
  20. export default {
  21. data() {
  22. return {
  23. xpjAudio: null,
  24. currentTime: 0,
  25. duration: 100,
  26. status: false
  27. }
  28. },
  29. props: {
  30. showImg: {
  31. type: Boolean,
  32. default: true
  33. },
  34. url: String,
  35. activeColor: {
  36. type: String,
  37. default: '#f00'
  38. },
  39. startImg: {
  40. type: String,
  41. default: '/static/imgs/voice/start.png'
  42. },
  43. pauseImg: {
  44. type: String,
  45. default: '/static/imgs/voice/pause.png'
  46. },
  47. blockColor: {
  48. type: String,
  49. default: '#FF0000'
  50. },
  51. backgroundColor: {
  52. type: String,
  53. default: '#eee'
  54. },
  55. blockSize: {
  56. type: Number,
  57. default: 14,
  58. },
  59. textColor: {
  60. type: String,
  61. default: '#f00'
  62. }
  63. },
  64. created() {
  65. this.xpjAudio = uni.createInnerAudioContext();
  66. this.xpjAudio.src = this.url;
  67. // uni.setInnerAudioOption({
  68. // obeyMuteSwitch: false
  69. // })
  70. this.onTimeUpdate();
  71. this.onCanplay();
  72. this.onEnded();
  73. uni.$on('stop', () => {
  74. this.xpjAudio.stop()
  75. this.status = false
  76. })
  77. },
  78. methods: {
  79. //开始播放事件
  80. startPlay() {
  81. if (this.status) {
  82. this.xpjAudio.pause();
  83. this.status = !this.status;
  84. } else {
  85. uni.$emit('stop')
  86. this.xpjAudio.seek(this.currentTime)
  87. this.xpjAudio.play()
  88. this.status = !this.status;
  89. }
  90. },
  91. //进入可播放状态
  92. onCanplay() {
  93. this.xpjAudio.onCanplay(() => {
  94. this.xpjAudio.duration;
  95. setTimeout(() => {
  96. this.duration = this.xpjAudio.duration;
  97. })
  98. })
  99. },
  100. //音频播放进度更新
  101. onTimeUpdate() {
  102. this.xpjAudio.onTimeUpdate(() => {
  103. this.currentTime = this.xpjAudio.currentTime;
  104. })
  105. },
  106. //播放结束事件
  107. onEnded() {
  108. this.xpjAudio.onEnded(() => {
  109. this.status = false;
  110. this.currentTime = 0;
  111. })
  112. },
  113. // 拖拽播放事件
  114. changeAudio(e) {
  115. let paused = this.xpjAudio.paused;
  116. this.xpjAudio.pause();
  117. this.xpjAudio.seek(e.detail.value)
  118. if (!paused) {
  119. this.xpjAudio.play();
  120. }
  121. },
  122. format(num) {
  123. return '0'.repeat(2 - String(Math.floor(num / 60)).length) + Math.floor(num / 60) + ':' + '0'.repeat(2 -
  124. String(Math.floor(num % 60)).length) + Math.floor(num % 60)
  125. },
  126. },
  127. destroyed() {
  128. this.xpjAudio.stop();
  129. },
  130. watch: {
  131. url(newVal) {
  132. if (newVal) {
  133. this.xpjAudio.stop();
  134. this.xpjAudio.src = newVal;
  135. this.currentTime = 0;
  136. this.onTimeUpdate();
  137. this.onCanplay();
  138. this.onEnded();
  139. this.status = false
  140. }
  141. }
  142. }
  143. }
  144. </script>
  145. <style lang="scss">
  146. .xpj-audio-box {
  147. width: 100%;
  148. text-align: center;
  149. padding: 30rpx;
  150. box-sizing: border-box;
  151. .title {
  152. font-size: 32rpx;
  153. font-weight: bold;
  154. padding: 40rpx 0 60rpx;
  155. }
  156. .voice {
  157. height: 100%;
  158. }
  159. .voice_icon {
  160. width: 100rpx;
  161. height: 100rpx;
  162. margin-bottom: 78rpx;
  163. }
  164. .play-btn {
  165. font-size: 0;
  166. margin-right: 10rpx;
  167. .play-icon {
  168. width: 40rpx;
  169. height: 40rpx;
  170. }
  171. }
  172. .time-text {
  173. font-size: 28rpx;
  174. }
  175. .audio-action {
  176. flex: 1;
  177. }
  178. }
  179. </style>