audio.nvue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. <template name="dever-audio">
  2. <view class="control">
  3. <view>
  4. <bing-lyric :lyrics="lyrics" :centerStyle="centerStyle" :curTime="currentTimeSecond" :areaStyle="cuAreaStyle" :selectControlStyle="selectControlStyle" :lyricStyle="lyricStyle"
  5. @centerBtnClick="centerBtnClick" @copyLyrics="copy"></bing-lyric>
  6. </view>
  7. <view class="audio">
  8. <view class="audio-wrapper">
  9. <view class="audio-number">{{currentTime}}</view>
  10. <slider class="audio-slider" :activeColor="color" block-size="16" :value="current" :max="duration" @changing="seek=true,current=$event.detail.value"
  11. @change="change"></slider>
  12. <view class="audio-number">{{durationTime}}</view>
  13. </view>
  14. <view class="audio-controll">
  15. <cover-image class="image" v-if="!recycleStatus" @click="setRecycle" src="@/static/music/recycle.png" mode="aspectFit"></cover-image>
  16. <cover-image class="image" v-if="recycleStatus" @click="setRecycle" src="@/static/music/recycled.png" mode="aspectFit"></cover-image>
  17. <cover-image class="image" @click="last" src="@/static/music/last.png" mode="aspectFit"></cover-image>
  18. <cover-image class="image" v-if="!play" @click="open" src="@/static/music/play.png" mode="aspectFit"></cover-image>
  19. <cover-image class="image" v-if="play" @click="open" src="@/static/music/pause.png" mode="aspectFit"></cover-image>
  20. <cover-image class="image" @click="next" src="@/static/music/next.png" mode="aspectFit"></cover-image>
  21. </view>
  22. </view>
  23. </view>
  24. </template>
  25. <script>
  26. import bingLyric from '@/lib/bing-lyric/bing-lyric.vue'
  27. import copyText from "@/lib/clipboard.thorui.js";
  28. export default {
  29. name: "dever-audio",
  30. props: {
  31. src : {
  32. type : String,
  33. value : null
  34. },
  35. loop : {
  36. type : Boolean,
  37. value : false
  38. },
  39. pic : {
  40. type : String,
  41. value : null
  42. },
  43. auto : {
  44. type : Boolean,
  45. value : false
  46. },
  47. control : {
  48. type : Boolean,
  49. value : false
  50. },
  51. color: {
  52. type:String,
  53. default:'#169af3'
  54. },
  55. title : '',
  56. singer : '',
  57. lrc : '',
  58. lrc_color : '',
  59. lrc_atcolor : '',
  60. recycle : '',
  61. },
  62. components:{
  63. bingLyric
  64. },
  65. data() {
  66. return {
  67. objectFit : 'fill',
  68. play : false,
  69. playButton : false,
  70. audio : false,
  71. recycleStatus : false,
  72. top : 0,//图片位置
  73. currentTime: '', //当前播放时间
  74. duration:'',
  75. durationTime: '', //总时长
  76. current: '', //slider当前进度
  77. loading: false, //是否处于读取状态
  78. paused: true, //是否处于暂停状态
  79. seek: false ,//是否处于拖动状态
  80. currentTimeSecond: 0,//当前播放秒数
  81. centerStyle: {
  82. btnImg: '../../static/music/btn.png',
  83. },
  84. lyricStyle: {
  85. color: this.lrc_color ,//歌词颜色,
  86. activeColor: this.lrc_atcolor ,//当前播放的歌词的颜色,
  87. fontSize: '16px' ,//歌词字体尺寸
  88. activeFontSize: '16px' ,//当前播放的歌词的字体尺寸
  89. lineHeight: '40px' ,//每句歌词的显示区域的高度 以此来调整歌词间距
  90. activeLineHeight: '32px' ,//当前播放歌词的显示区域的高度
  91. selectedBGColor: 'inherit' ,//进入歌词选择模式时,被选择的歌词背景颜色
  92. },
  93. cuAreaStyle: {
  94. width: '100vw',
  95. height: '100vh',
  96. background : 'url('+this.pic+')',
  97. },
  98. selectControlStyle : {
  99. color : 'white',
  100. itemBackgroundColor : '#333333',
  101. backgroundColor : 'rgba(0,0,0,0)',
  102. },
  103. lyrics: [],
  104. };
  105. },
  106. watch: {
  107. //监听总时长改变
  108. duration(e) {
  109. //this.durationTime = this.format(e)
  110. },
  111. //监听当前进度改变
  112. current(e) {
  113. this.currentTime = this.format(e)
  114. this.currentTimeSecond = e;
  115. }
  116. },
  117. mounted() {
  118. //考虑换成getBackgroundAudioManager()
  119. if (this.Dever.source == 'h5') {
  120. this.audio = uni.createInnerAudioContext()
  121. } else {
  122. this.audio = uni.getBackgroundAudioManager()
  123. this.audio.title = this.title;
  124. this.audio.singer = this.singer;
  125. this.audio.coverImgUrl = this.pic;
  126. }
  127. this.audio.src = this.src;
  128. //this.audio.loop = this.loop;
  129. this.recycleStatus = this.recycle;
  130. if (!this.lrc) {
  131. this.lyrics = [];
  132. this.top = '0';
  133. } else {
  134. this.lyrics = this.lrc;
  135. this.top = '0';
  136. }
  137. this.current = 0;
  138. this.audio.obeyMuteSwitch = false;
  139. this.audio.autoplay = this.auto;
  140. //音频进度更新事件
  141. this.audio.onTimeUpdate(() => {
  142. if (!this.seek) {
  143. this.current = this.audio.currentTime;
  144. }
  145. if (!this.durationTime) {
  146. this.duration = this.audio.duration;
  147. this.durationTime = this.format(this.audio.duration);
  148. }
  149. })
  150. //音频完成更改进度事件
  151. this.audio.onSeeked(() => {
  152. this.seek = false;
  153. })
  154. //音频播放完成事件
  155. this.audio.onEnded(() => {
  156. if (this.recycleStatus) {
  157. // 播放下一曲
  158. this.next();
  159. } else {
  160. this.play = false;
  161. this.playButton = false;
  162. this.audio.seek(0);
  163. this.start();
  164. }
  165. });
  166. },
  167. methods:{
  168. start : function() {
  169. this.$emit('update:load', true);
  170. if (!this.play) {
  171. this.audio.play();
  172. this.play = true;
  173. this.playButton = true;
  174. }
  175. },
  176. stop : function() {
  177. if (this.play) {
  178. this.audio.pause();
  179. this.play = false;
  180. this.playButton = false;
  181. }
  182. },
  183. open : function() {
  184. if (!this.play) {
  185. this.start();
  186. } else {
  187. this.stop(true);
  188. }
  189. },
  190. //上一曲
  191. last : function() {
  192. this.$emit('last');
  193. },
  194. //下一曲
  195. next : function() {
  196. this.$emit('next');
  197. },
  198. //多曲循环播放
  199. setRecycle : function() {
  200. this.recycleStatus = !this.recycleStatus;
  201. this.$emit('setRecycle');
  202. },
  203. //格式化时长
  204. format : function(num) {
  205. return '0'.repeat(2 - String(Math.floor(num / 60)).length) + Math.floor(num / 60) + ':' + '0'.repeat(2 - String(
  206. Math.floor(num % 60)).length) + Math.floor(num % 60)
  207. },
  208. //完成拖动事件
  209. change : function(e) {
  210. this.audio.seek(e.detail.value)
  211. },
  212. copy : function(e) {
  213. var self = this;
  214. var value = '';
  215. for (var i in e.lyrics) {
  216. value += e.lyrics[i] + "\r\n";
  217. }
  218. copyText.getClipboardData(value, function(res) {
  219. if (res) {
  220. self.Dever.alert('复制成功');
  221. } else {
  222. self.Dever.alert('复制失败');
  223. }
  224. });
  225. },
  226. centerBtnClick : function(e) {
  227. this.currentTimeSecond = e.centerTime
  228. this.audio.seek(this.currentTimeSecond);
  229. },
  230. },
  231. }
  232. </script>
  233. <style scoped>
  234. .control {
  235. width: 100%;
  236. height: 100%;
  237. z-index: 2;
  238. background: transparent;
  239. position: absolute;
  240. left: 0;
  241. top: 0;
  242. overflow: hidden;
  243. }
  244. .poster{
  245. background-size: cover;
  246. position: absolute;
  247. left: 0;
  248. top: 0;
  249. width: 100%;
  250. height: 100%;
  251. }
  252. .audio {
  253. padding: 24rpx;
  254. background: #fff;
  255. border-radius: 20rpx;
  256. position: absolute;
  257. z-index: 100;
  258. background: #666666;
  259. background: hsla(0,0%,100%,.6);
  260. bottom: 10rpx;
  261. left: 20rpx;
  262. width: 78%;
  263. }
  264. .audio-wrapper {
  265. display: flex;
  266. align-items: center;
  267. }
  268. .audio-number {
  269. font-size: 24rpx;
  270. line-height: 1;
  271. color: #333;
  272. color: #fff;
  273. }
  274. .audio-slider {
  275. flex: 1;
  276. margin: 0 30rpx;
  277. }
  278. .audio-controll {
  279. display: flex;
  280. justify-content: space-around;
  281. margin-top: 26rpx;
  282. }
  283. .audio-controll .image {
  284. display: inline-block;
  285. height: 30rpx;
  286. width: 30rpx;
  287. }
  288. </style>