uni-app实现全局音乐播放器

项目需要,要求每一页内需要有一个播放器,管理播放状态以及切换歌曲

实现思路:vuex存储播放状态以及歌曲列表等信息

  1. 根目录下创建store目录
  2. store下创建music.js

music.js内容

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
	state: {
		url:'',//地址
		max:0,//总时长
		schedule:0,//进度
		list:[],//目录
		music:uni.createInnerAudioContext(),//创建播放器对象
		is_bf:false,//当前播放状态
		index:0,//索引
	},
	mutations: {
		//设置播放列表
		setList(state,list){
			state.list=list;
		},
		//设置播放路径
		setMusicUrl(state,index) {
			console.log(index)
			//设置索引
			state.index=index;
			//设置路径
			state.url = state.list[index].url;
			//播放器引入url
			state.music.src = state.list[index].url;
			//初始化播放进度
			state.music.startTime=0;
			//开始播放
			state.music.play(); //执行播放
			//设置播放状态
			state.is_bf=true;
			//获取播放进度
			state.music.onTimeUpdate(() => {
				//设置总时长
				state.max=state.music.duration;
				//修改进度
				state.schedule=state.music.currentTime;
			})
		},
		//修改播放进度
		setSchedule(state,num) {
			state.schedule = state.max*num;
			state.music.currentTime=state.schedule;
		},
		//开始播放音频
		play(state,num) {
			state.is_bf=true;
			state.music.play();
		},
		//暂停当前播放的音频
		pause(state,num) {
			state.is_bf=false;
			state.music.pause();
		},
	},
})
export default store

components目录下新建music.vue

<template>
	<view class="music_box">
		<view class="left_box">
			<view class="prev" @click="prev(index)">
				上一首
			</view>
			<view class="bf" @click="setBf(!is_bf)">
				<view v-if="!is_bf">播放</view>
				<view v-else>暂停</view>
			</view>
			<view class="next" @click="next(index,list)">
				下一首
			</view>
		</view>
		<!-- 进度条 -->
		<view class="jd_box" @click="getXy">
			<view class="jd_n" :style="{width:schedule/max*100+'%'}"></view>
		</view>
		<!-- 时间 -->
		<view class="timer_box">
			{{getTimer(schedule)}}/{{getTimer(max)}}
		</view>
		<view class="list_icon" @click.stop="list_show=true">
			列表
			<view class="list_box" v-show="list_show" :style="{height:list.length*30+'px'}" >
				<view v-for="(item,id) in list" :class="{active:index==id}" @click.stop="setIndex(id)">
					{{item.title}}
				</view>
			</view>
		</view>
		<!-- {{schedule}}/{{max}} -->
	</view>
</template>
<script>
	import {
		mapGetters,
		mapMutations,
		mutations,
		mapState
	} from 'vuex'
	export default {
		data() {
			return {
				list_show:false,
			}
		},
		//监听数据发生变化
		watch: {
			schedule(val) {
				
			}
		},
		created() {

		},
		mounted() {
			// this.setSchedule('123');//修改进度条时间
		},
		computed: {
			...mapState(["schedule", "url", "max", "list","is_bf","index"])
		},
		methods: {
			...mapMutations(['setSchedule', 'setTestArrInc','play','pause','setMusicUrl']),
			prev(index){
				if(index<=0){
					return
				}
				this.setMusicUrl(index-1)
			},
			next(index,list){
				if(index>=list.length-1){
					return
				}
				this.setMusicUrl(index+1)
			},
			setIndex(index){
				this.setMusicUrl(index);
				this.list_show=false;
			},
			getTimer(second) {
				let h = parseInt(second / 60 / 60 % 24);
				h = h < 10 ? '0' + h : h;
				let m = parseInt(second / 60 % 60);
				m = m < 10 ? '0' + m : m;
				let s = parseInt(second % 60);
				s = s < 10 ? '0' + s : s;
				let res = [h, m, s];
				return res[0]+':'+res[1]+':'+res[2]
			},
			getXy(e){
				console.log((e.detail.x-(e.currentTarget.offsetLeft*(document.documentElement.clientWidth/1920))))
				this.setSchedule(((e.detail.x/(document.documentElement.clientWidth/1920))-e.currentTarget.offsetLeft)/500);
			},
			//设置播放状态
			setBf(is){
				if(is){
					this.play();
				}else{
					this.pause();
				}
			}
		},
	}
</script>

<style>
	.music_box {
		width: 100%;
		height: 80px;
		background-color: rgba(0,0,0,0.7);
		position: fixed;
		bottom: 0;
		left: 0;
		z-index: 99;
		display: flex;
		color: #fff;
		align-items: center;
		padding: 0 60px;
		box-sizing: border-box;
		justify-content: center;
		font-size: 20px;
	}
	.left_box{
		margin-right: 20px;
		display: flex;
		align-items: center;
	}
	.bf{
		width: 50px;
		height: 50px;
		border: 2px solid #fff;
		border-radius: 50%;
		display: flex;
		align-items: center;
		justify-content: center;
		margin: 0 20px;
	}
	.jd_box{
		width: 500px;
		height: 15px;
		background-color: rgba(255,255,255,0.5);
		margin-right: 20px;
		position: relative;
	}
	.jd_n{
		height: 100%;
		background-color: rgba(255,255,255,0.8);
	}
	.list_icon{
		margin-left: 20px;
		padding: 5px;
		border: 1px solid #fff;
		position: relative;
	}
	.list_box{
		width: 200px;
		position: absolute;
		left: 0;
		background-color: rgba(0,0,0,0.7);
		bottom: 60px;
	}
	.list_box>view{
		width: 100%;
		text-align: center;
		font-size: 16px;
		line-height: 30px;
		border-bottom: 1px solid #ccc;
	}
	.active{
		background: red;
	}
</style>

在需要播放器的页面内应用

<script>
	import {
		mapGetters,
		mapMutations,
		mutations,
		mapState
	} from 'vuex'
	export default {
		data() {
			return {
				
			}
		},
		onLoad() {
		},
		methods: {
			...mapMutations(['setList','setSchedule', 'setMusicUrl']),
		},
		mounted() {
            //设置目录
			this.setList([{
				title:'第一回',
				url:'http://sns-oss.oss-cn-beijing.aliyuncs.com/masterpieces/28/001.mp3'
			},{
				title:'第二回',
				url:'http://sns-oss.oss-cn-beijing.aliyuncs.com/masterpieces/28/002.mp3'
			}]);
            //设置播放索引
			this.setMusicUrl(0);
		}
	}
</script>


版权声明:本文为m0_52035863原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。