audioPlayer.vue 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. <template>
  2. <div>
  3. <audio @timeupdate="updateProgress" controls :ref="refId" style="display: none">
  4. <source :src="'http://192.168.1.43/api/'+fileurl" type="audio/mpeg" />
  5. 您的浏览器不支持音频播放
  6. </audio>
  7. <div class="audio-right">
  8. <i :class="audioStatus !== 'pause' ? 'iconfont el-icon-video-play' : 'iconfont el-icon-video-pause'"
  9. @click="playAudio" class="dialogAudioPlay"></i>
  10. <div class="progress-bar-bg" :id="refId" v-dragto="setAudioIcon">
  11. <div class="progress-bar" :id="refId+'bar'"></div>
  12. </div>
  13. <div class="audio-time" style="min-height: 10px">
  14. <span class="audio-length-current" id="audioCurTime">{{ audioStart }}</span
  15. >
  16. <span style="padding:0 4px;">/</span>
  17. <span class="audio-length-total">{{ duration }}</span>
  18. </div>
  19. <div class="volume">
  20. <div
  21. @click.stop="
  22. () => {
  23. return false
  24. }
  25. "
  26. class="volume-progress"
  27. v-show="audioHuds"
  28. >
  29. <div class="volume-bar-bg" id="volumeBarBg" v-adjuster="handleShowMuteIcon">
  30. <div class="volume-bar" id="volumeBar"></div>
  31. </div>
  32. </div>
  33. <i class="iconfont pl-1" :class="audioIcon" @click.stop="audioHuds = !audioHuds"> </i>
  34. </div>
  35. </div>
  36. </div>
  37. </template>
  38. <script>
  39. export default {
  40. props: {
  41. fileurl: {
  42. trpe: String
  43. },
  44. refId: {
  45. trpe: String
  46. }
  47. },
  48. data() {
  49. return {
  50. audioStatus: 'play',
  51. audioStart: '0:00',
  52. duration: '0:00',
  53. audioVolume: 0.5,
  54. audioHuds: false
  55. }
  56. },
  57. directives: {
  58. dragto: {
  59. inserted: function (el, binding, vnode) {
  60. el.addEventListener(
  61. 'click',
  62. (e) => {
  63. let wdiv = document.getElementById(this.refId).clientWidth
  64. let audio = vnode.context.$refs[this.refId]
  65. // 只有音乐开始播放后才可以调节,已经播放过但暂停了的也可以
  66. let ratemin = e.offsetX / wdiv
  67. let rate = ratemin * 100
  68. document.getElementById(this.refId+'bar').style.width = rate + '%'
  69. audio.currentTime = audio.duration * ratemin
  70. audio.play()
  71. binding.value()
  72. },
  73. false
  74. )
  75. }
  76. },
  77. adjuster: {
  78. inserted: function (el, binding, vnode) {
  79. el.addEventListener(
  80. 'click',
  81. (e) => {
  82. let hdiv = document.getElementById('volumeBarBg').clientHeight
  83. let audio = vnode.context.$refs[this.refId]
  84. // 只有音乐开始播放后才可以调节,已经播放过但暂停了的也可以
  85. let ratemin = e.offsetY / hdiv
  86. let rate = ratemin * 100
  87. document.getElementById('volumeBar').style.height = rate + '%'
  88. audio.volume = ratemin
  89. binding.value(rate / 100)
  90. },
  91. false
  92. )
  93. }
  94. }
  95. },
  96. computed: {
  97. audioIcon() {
  98. if (this.audioHuds) {
  99. return this.audioVolume < 0.01 ? 'checked icon-jingyin' : 'checked icon-shengyin'
  100. } else {
  101. return 'icon-shengyin'
  102. }
  103. }
  104. },
  105. mounted() {
  106. this.fetch()
  107. },
  108. methods: {
  109. fetch() {
  110. let that = this
  111. var myVid = this.$refs[this.refId]
  112. myVid.loop = false
  113. // 监听音频播放完毕
  114. myVid.addEventListener(
  115. 'ended',
  116. function () {
  117. that.audioStatus = 'play' // 显示播放icon
  118. document.getElementById(this.refId+'bar').style.width = '0%' // 进度条初始化
  119. },
  120. false
  121. )
  122. if (myVid != null) {
  123. myVid.oncanplay = function () {
  124. that.duration = that.transTime(myVid.duration)=='NaN:NaN'?'0:00':that.transTime(myVid.duration) // 计算音频时长
  125. }
  126. myVid.volume = 1 // 设置音量100%
  127. }
  128. },
  129. // 播放暂停控制
  130. playAudio() {
  131. let recordAudio = this.$refs[this.refId] // 获取audio元素
  132. if (recordAudio.paused) {
  133. recordAudio.play()
  134. this.audioStatus = 'pause'
  135. } else {
  136. recordAudio.pause()
  137. this.audioStatus = 'play'
  138. }
  139. },
  140. // 更新进度条与当前播放时间
  141. updateProgress(e) {
  142. var value = e.target.currentTime / e.target.duration
  143. if (document.getElementById(this.refId+'bar')) {
  144. document.getElementById(this.refId+'bar').style.width = value * 100 + '%'
  145. if (e.target.currentTime === e.target.duration) {
  146. this.audioStatus = 'pause'
  147. }
  148. } else {
  149. this.audioStatus = 'pause'
  150. }
  151. this.audioStart = this.transTime(this.$refs[this.refId].currentTime)
  152. },
  153. /**
  154. * 音频播放时间换算
  155. * @param {number} value - 音频当前播放时间,单位秒
  156. */
  157. transTime(time) {
  158. var duration = parseInt(time)
  159. var minute = parseInt(duration / 60)
  160. var sec = (duration % 60) + ''
  161. var isM0 = ':'
  162. if (minute === 0) {
  163. minute = '00'
  164. } else if (minute < 10) {
  165. minute = '0' + minute
  166. }
  167. if (sec.length === 1) {
  168. sec = '0' + sec
  169. }
  170. return minute + isM0 + sec
  171. },
  172. setAudioIcon() {
  173. this.audioStatus = 'pause'
  174. },
  175. handleShowMuteIcon(val) {
  176. this.audioVolume = val
  177. }
  178. }
  179. }
  180. </script>
  181. <style lang="scss" scoped>
  182. .volume {
  183. position: relative;
  184. .volume-progress {
  185. position: absolute;
  186. top: -150px;
  187. width: 32px;
  188. height: 140px;
  189. background: #f6f6f6;
  190. border-radius: 4px;
  191. padding-top: 10px;
  192. }
  193. .volume-bar-bg {
  194. margin: 0 auto;
  195. width: 6px;
  196. height: 120px;
  197. background: #dcdcdc;
  198. border-radius: 100px;
  199. flex: 1;
  200. position: relative;
  201. transform: rotate(180deg);
  202. cursor: pointer;
  203. .volume-bar {
  204. width: 6px;
  205. height: 50%;
  206. background: #585959;
  207. border-radius: 100px;
  208. }
  209. }
  210. .checked {
  211. color: #585959;
  212. }
  213. }
  214. .audio-right {
  215. width: 100%;
  216. height: 49px;
  217. line-height: 49px;
  218. background: #dcdcdc;
  219. border-radius: 30px;
  220. display: flex;
  221. padding: 0 15px;
  222. .dialogAudioPlay {
  223. cursor: pointer;
  224. color: #5c5e66;
  225. font-size: 24px;
  226. line-height:49px;
  227. }
  228. .progress-bar-bg {
  229. background-color: #fff;
  230. flex: 1;
  231. position: relative;
  232. height: 4px;
  233. top: 50%;
  234. transform: translateY(-50%);
  235. margin-top: -1px;
  236. cursor: pointer;
  237. margin: 0 10px;
  238. }
  239. .progress-bar {
  240. background-color: #585959;
  241. width: 0%;
  242. height: 4px;
  243. border-radius: 5px;
  244. }
  245. .audio-time {
  246. overflow: hidden;
  247. font-size: 14px;
  248. .audio-length-total {
  249. float: right;
  250. }
  251. .audio-length-current {
  252. float: left;
  253. }
  254. }
  255. }
  256. </style>