">
赞
踩
uni-app中实现音乐播放器
1、主要利用的是uni-app中提供的uni.createInnerAudioContext()来进行实现;
2、代码示例
(1)主页面代码展示
<template> <view class="songDetailContainer"> <view class="bg" :style="{ backgroundImage: `url(${song.imageUrl})` }"></view> <view class="content"> <view class="title">{{ song.title }}</view> <view class="discContainer discAnimation" v-show="current == 0"> <view class="disc"></view> <view class="circle"> <image class="musicImg" :src="song.imageUrl"></image> </view> </view> <scroll-view class="h-full" :scroll-y="true" :refresher-enabled="false" :scroll-anchoring="true" v-show="current == 1" > <view class="prompt" v-html="song.lyric" style="white-space: pre-line"> </view> </scroll-view> <u-tabs class="u-tabs-con" :list="list1" @change="handleChange" :current="current" :scrollable="true" active-color="#fff" inactive-color="#ccc4c2" :gutter="20" :bar-width="20" ></u-tabs> <view class="share"> <u-icon name="share" color="#fff" size="40" @click="shareClick"></u-icon> <text> 分享 </text> </view> <!-- 进度条控制区域 --> <view class="progressControl"> <text>{{ currentTimeText }}</text> <slider style="width: 560rpx" @change="handleSliderChange" :value="sliderIndex" :max="maxSliderIndex" activeColor="#ea588e" backgroundColor="#b9c2c5" block-color="#fff" block-size="12" /> <text>{{ totalTimeText }}</text> </view> <!-- 底部控制播放区域 --> <view class="musicControl"> <u-icon name="star" color="#fff" size="60" @click="starClick"></u-icon> <u-icon name="rewind-left-fill" @click="handlePrev" color="#fff" size="60" id="pre" ></u-icon> <u-icon name="pause-circle-fill" @click="onPauseAudio" v-if="isPlay" color="#fff" size="80" ></u-icon> <u-icon name="play-circle-fill" @click="onPlayAudio" v-else color="#fff" size="80" ></u-icon> <u-icon name="rewind-right-fill" @click="handleNext" color="#fff" size="60" id="next" ></u-icon> <u-icon name="grid" @click="show = true" color="#fff" size="60"></u-icon> </view> </view> </view> <u-action-sheet class="action-sheet" :list="data.list" v-model="show" @click="sheetClick" cancel-text="关闭" ></u-action-sheet> <!-- #ifdef H5 --> </template> <script lang="ts" setup> import { ref, reactive, onUnmounted } from 'vue' import moment from 'moment' import { onLoad } from '@dcloudio/uni-app' import { download } from '@/utils/download' import { drawingRecord } from '@/api/music' let id = ref(0) // 歌曲详情对象 const song = ref({}) // 歌曲详情对象 const isPlay = ref(false) // 音乐是否播放 const currentTime2 = ref(0) // 实时时间 const audioList = ref([]) // 音乐列表 let index = 0 const show = ref(false) const innerAudioContext = uni.createInnerAudioContext() const startId = ref(0) const endId = ref(0) const sliderIndex = ref(0) //滑块当前值 const maxSliderIndex = ref(100) //滑块最大值 const currentTimeText = ref('00:00') //视频已播放长度文字 const totalTimeText = ref('00:00') //视频总长度文字 onLoad((options: any) => { id.value = options.id startId.value = options.startId endId.value = options.endId getAudioList() }) const getAudioList = async () => { const { lists } = await drawingRecord({ status: 3, startId: startId.value, endId: endId.value, pageNo: 1, pageSize: 100 }) audioList.value = lists for (let i = 0; i < audioList.value.length; i++) { if (audioList.value[i].id == id.value) { index = i console.info('index', i) } } song.value = audioList.value[index] innerAudioContext.autoplay = true innerAudioContext.src = song.value.audioUrl innerAudioContext.play() isPlay.value = true } innerAudioContext.onEnded(() => { isPlay.value = false currentTimeText.value = '00:00' sliderIndex.value = 0 handleNext() }) innerAudioContext.onTimeUpdate(() => { currentTimeText.value = moment(innerAudioContext.currentTime * 1000).format('mm:ss') sliderIndex.value = innerAudioContext.currentTime }) innerAudioContext.onCanplay(function () { totalTimeText.value = moment(innerAudioContext.duration * 1000).format('mm:ss') maxSliderIndex.value = innerAudioContext.duration }) innerAudioContext.onPause(() => { currentTime2.value = innerAudioContext.currentTime }) innerAudioContext.onPlay(() => { innerAudioContext.seek(currentTime2.value) console.log(currentTime2.value, 'currentTime2.value') }) const onPauseAudio = () => { innerAudioContext.pause() isPlay.value = false } const onPlayAudio = () => { innerAudioContext.src = song.value.audioUrl innerAudioContext.play() isPlay.value = true } const handlePrev = () => { innerAudioContext.stop() sliderIndex.value = 0 currentTimeText.value = '00:00' currentTime2.value = 0 if (index == 0) { index = audioList.value.length } innerAudioContext.src = audioList.value[index - 1].audioUrl song.value.title = audioList.value[index - 1].title song.value.imageUrl = audioList.value[index - 1].imageUrl song.value.duration = audioList.value[index - 1].duration song.value.lyric = audioList.value[index - 1].lyric innerAudioContext.play() isPlay.value = true index -= 1 console.log(index, 'index') } const handleNext = () => { innerAudioContext.stop() sliderIndex.value = 0 currentTimeText.value = '00:00' currentTime2.value = 0 console.log(sliderIndex.value, currentTimeText.value, '下一首') if (index == audioList.value.length - 1) { index = -1 } innerAudioContext.src = audioList.value[index + 1].audioUrl song.value.title = audioList.value[index + 1].title song.value.imageUrl = audioList.value[index + 1].imageUrl song.value.duration = audioList.value[index + 1].duration song.value.lyric = audioList.value[index + 1].lyric innerAudioContext.play() isPlay.value = true index += 1 console.log(index, 'index') } // 文件下载 const onFileDownload = async (drawing: any) => { uni.setClipboardData({ data: drawing, success: function () { uni.showToast({ title: '复制成功,请打开浏览器下载', duration: 2000 }) } }) } const data = reactive({ list: [ { text: '下载音频', fontSize: 28 }, { text: '下载视频', fontSize: 28 } ] }) const sheetClick = (index: number) => { if (index == 0) { onFileDownload(song.value.audioUrl) } else if (index == 1) { onFileDownload(song.value.videoUrl) } } //变更滑块位置 const handleSliderChange = (e) => { changePlayProgress(e.detail ? e.detail.value : e) } //更改播放进度 const changePlayProgress = (value: any) => { sliderIndex.value = value innerAudioContext.seek(value) currentTimeText.value = moment(value * 1000).format('mm:ss') } // tabs部分 const current = ref(0) const list1 = ref([ { customMode: 0, name: '歌曲' }, { customMode: 1, name: '歌词' } ]) const handleChange = (index: number) => { current.value = index } const starClick = () => { uni.showToast({ title: '敬请期待' }) } const shareClick = () => { uni.showToast({ title: '敬请期待' }) } onUnmounted(() => { innerAudioContext.destroy() }) </script> <style lang="scss" scoped> .songDetailContainer { height: 100vh; width: 100%; position: relative; .bg { width: 100%; height: 100vh; position: absolute; z-index: 0; background-size: cover; background-repeat: no-repeat; filter: blur(60px); } .content { display: flex; justify-content: space-around; flex-direction: column; align-items: center; .title { color: #fff; position: absolute; top: 30rpx; } .prompt { color: #fff; position: absolute; top: 80rpx; left: 40rpx; right: 40rpx; font-size: 38rpx; line-height: 68rpx; } .h-full { position: absolute; top: 120rpx; left: 40rpx; right: 40rpx; height: 800rpx; width: calc(100% - 80rpx); } .u-tabs-con { position: absolute; bottom: 300rpx; color: #fff; } } } .content ::v-deep .u-tabs { background: none !important; } .share { position: absolute; bottom: 320rpx; right: 50rpx; color: #fff; display: flex; align-items: center; text { margin-left: 10rpx; font-size: 24rpx; } } /* 磁盘 */ .discContainer { position: relative; top: 200rpx; // width: 598rpx; // height: 598rpx; width: 490rpx; height: 490rpx; border: 1rpx solid #e6e6e6; border-radius: 50%; } .discAnimation { animation: disc 8s linear infinite; animation-delay: 1s; } /* @keyframes: 设置动画帧 1) from to - 使用于简单的动画,只有起始帧和结束帧 - 北京 - 上海 直达 2) 百分比 - 多用于复杂的动画,动画不止两帧 - 北京 - 上海 ---> 北京 -- 天津 --- 深圳 --- 上海 - 0% - 100%, 可以任意拆分 */ @keyframes disc { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } .disc { width: 100%; height: 100%; } .songDetailContainer .discContainer .musicImg { position: absolute; left: 0; right: 0; top: 0; bottom: 0; margin: auto; width: 370rpx; height: 370rpx; border: 1rpx solid transparent; border-radius: 50%; } .circle { position: absolute; left: 30rpx; top: 30rpx; width: 430rpx; height: 430rpx; border: 1rpx solid #e6e6e6; border-radius: 50%; } /* 底部控制播放区域 */ .musicControl { position: absolute; bottom: 80rpx; left: 60rpx; width: calc(100% - 120rpx); display: flex; justify-content: space-between; } .musicControl text { width: 20%; height: 120rpx; line-height: 120rpx; text-align: center; color: #fff; font-size: 50rpx; } .musicControl text.big { font-size: 80rpx; } /* 进度条控制区域 */ .progressControl { position: absolute; bottom: 200rpx; width: 640rpx; height: 80rpx; line-height: 80rpx; display: flex; color: #fff; } .action-sheet ::v-deep .u-action-sheet-item { align-items: baseline; padding-left: 30rpx; } </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。