Vue开发历程---音乐播放器的继续
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue开发历程---音乐播放器的继续相关的知识,希望对你有一定的参考价值。
前言
前面一篇文章Vue开发历程---音乐播放器,实现了播放音乐,以及基本的布局。但是进度条没有实现同步,本文即介绍进度条的实现。
一、效果图
二、心路历程
1、elementUI 滑块的使用
<div class="block" style="margin-top:5px">
<el-slider v-model="value" @change="updateSlideTime()" :format-tooltip="formatTooltip"></el-slider>
</div>
2、JS的编写
进度条的状态是实时的,也就是每一秒每一刻都要变化,如何实现这一功能? 首先需要写一个方法,每30ms更新一次状态,同时在组件挂载完成的时候调用这个方法,从而实现了每30ms,即更新进度条的数值。 通过refs可以获得audio这个标签,这个标签上有duration(时长),currentTime(当前时间)这两个属性,通过这两个属性,可以计算出来进度的占比。
updateSongsTime: function ()
const timer = setInterval(() =>
const music = document.getElementById("m_mp3")||null;
if (music != null)
this.currentTime = music.currentTime;
this.duration = music.duration;
this.persent = (this.currentTime / this.duration) * 100;
, 30);
mounted()
this.songNum = this.songNames.length;
const music = this.$refs.player;
this.updateSongsTime();
同时也需要在MusicPlayer.vue组件里面如法炮制,获取父组件的值从而实时更新滑块的状态,因为滑块是写在MusicPlayer组件里面了,但是歌曲的播放在父组件Player.vue里,所以也是用到了组件的通信。
3、时间的转化
由于currentTime返回来的是总秒数,而音乐播放器一般都是分:秒这样的格式,所以通过一些简单的数学计算(除以60求分,对60取余求秒)来进行对时长的格式化处理。采用了三目运算符,还对不足10的时间进行了处理,即小于10的数值前面自动补0
formatTooltip()
return Math.trunc(this.$parent.currentTime/60)+":"+((Math.trunc(this.$parent.currentTime%60)<10)?("0"+Math.trunc(this.$parent.currentTime%60)):Math.trunc(this.$parent.currentTime%60));
#源代码
代码如下: Player.vue
<template>
<div class="player_div1">
<transition name="open" mode="out-in">
<component v-bind:is="view" @hello="changeSlideState" @play="changePlayState" @lastSongs="lastSongs"
@nextSongs="nextSongs" @changeSongsTime="changeSongsTime"></component>
</transition>
<audio class="m_mp3" id="m_mp3" :src="this.songNames[this.index].Url" autoplay loop ref="player" controls
style="display:none">
</audio>
</div>
</template>
<script>
import HidePlayer from @/part/HidePlayer
import MusicPlayer from @/part/MusicPlayer
export default
name: Player,
data()
return
view: MusicPlayer,
isClose: false,
isShow: true,
isRun: come,
index: 0,
songNum: 2,
currentTime: 0,
duration: 0,
persent: 0,
songNames: [
id: 6,
name: 庐州月-许嵩,
Url: require(@/assets/庐州月.mp3),
png: require(@/assets/庐州月.png),
,
id: 7,
name: 燕归巢-许嵩,
Url: require(@/assets/燕归巢.mp3),
png: require(@/assets/燕归巢.jpg),
,
id: 1,
name: 张韶涵-篇章,
Url: require(@/assets/张韶涵-篇章.mp3),
png: require(@/assets/篇章.png),
,
id: 2,
name: 爱就一个字 抒情版,
Url: require(@/assets/爱就一个字 抒情版.mp3),
png: require(@/assets/爱就一个字.png),
,
id: 3,
name: 最伟大的作品-周杰伦,
Url: require(@/assets/最伟大的作品-周杰伦.mp3),
png: require(@/assets/周杰伦.jpg),
,
id: 4,
name: 等你下课 (with 杨瑞代)-周杰伦,
Url: require(@/assets/等你下课 (with 杨瑞代)-周杰伦.mp3),
png: require(@/assets/等你下课.png),
,
id: 5,
name: 告白气球-周杰伦,
Url: require(@/assets/告白气球-周杰伦.mp3),
png: require(@/assets/告白气球.png),
,
id: 6,
name: 还在流浪-周杰伦,
Url: require(@/assets/还在流浪-周杰伦.mp3),
png: require(@/assets/还在流浪.png),
,
]
,
components:
HidePlayer,
MusicPlayer
,
methods:
changeSlideState()
this.isClose = !this.isClose;
if (this.isClose)
this.view = HidePlayer;
else
this.view = MusicPlayer;
,
changePlayState()
if (!this.isShow)
this.isShow = true;
this.isRun = "come";
document.getElementById("m_mp3").pause();
else
this.isShow = false;
this.isRun = "go";
var my_mp3 = document.getElementById("m_mp3");
my_mp3.play();
,
nextSongs()
if (this.isShow)
this.isShow = false;
this.isRun = "go";
this.index = (this.index + 1) % this.songNum;
,
lastSongs()
if (this.isShow)
this.isShow = false;
this.isRun = "go";
if (this.index == 0)
this.index = this.songNum - 1;
else
this.index = this.index - 1;
,
changeSongsTime(value)
const music = document.getElementById("m_mp3");
music.currentTime = value / 100 * music.duration;
,
updateSongsTime: function ()
const timer = setInterval(() =>
const music = document.getElementById("m_mp3")||null;
if (music != null)
this.currentTime = music.currentTime;
this.duration = music.duration;
this.persent = (this.currentTime / this.duration) * 100;
, 30)
, mounted()
this.songNum = this.songNames.length;
const music = this.$refs.player;
this.updateSongsTime();
</script>
<style scoped>
.open-enter-active
animation: slide-in linear 0.5s;
.open-leave-active
animation: slide-in reverse linear 0.5s;
@keyframes slide-in
from
transform: translateX(-100%);
to
transform: translateX(0%);
</style>
MusicPlayer.vue
<template>
<div class="music">
<!-- 占位 -->
<div class="m_hold">
</div>
<div class="m_img">
<img :src="this.$parent.songNames[this.$parent.index].png" :class="this.$parent.isRun">
</div>
<!-- 歌曲信息 -->
<div class="m_text">
this.$parent.songNames[this.$parent.index].name
<div class="block" style="margin-top:5px">
<el-slider v-model="value" @change="updateSlideTime()" :format-tooltip="formatTooltip"></el-slider>
</div>
</div>
<!-- 音乐时间信息 -->
<div class="m_time">
<span>nowtime / </span>
<span>allTime</span>
</div>
<!-- 按钮 -->
<div class="m_btn">
<a href="#" class="m_prev" @click="playLastSong()"></a>
<a href="#" class="m_play" @click="changeState()" v-show="this.$parent.isShow"></a>
<a href="#" class="m_pause" @click="changeState()" v-show="!this.$parent.isShow"></a>
<a href="#" class="m_next" @click="playNextSong()"></a>
</div>
<!-- 折叠功能 -->
<div class="m_close" @click="changeCloseState()">
<a href=""></a>
</div>
</div>
</template>
<script>
export default
name: MusicPlayer,
data()
return
songName: ,
value:0.0,
,
methods:
changeState()
this.$emit("play")
,
changeCloseState()
this.$emit("hello");
,
playNextSong()
this.$emit("nextSongs");
this.songName = this.$parent.songNames[this.$parent.index].name
,
playLastSong()
this.$emit("lastSongs");
this.songName = this.$parent.songNames[this.$parent.index].name
,
changeSlideTime()
const timer = setInterval(()=>
this.value = this.$parent.persent;
,30)
,
updateSlideTime()
this.$emit("changeSongsTime",this.value);
,
formatTooltip()
return Math.trunc(this.$parent.currentTime/60)+":"+((Math.trunc(this.$parent.currentTime%60)<10)?("0"+Math.trunc(this.$parent.currentTime%60)):Math.trunc(this.$parent.currentTime%60));
,
watch:
,
computed:
nowtime()
return ((Math.trunc(this.$parent.currentTime/60)<10)?("0"+Math.trunc(this.$parent.currentTime/60)):(Math.trunc(this.$parent.currentTime/60)))+":"+((Math.trunc(this.$parent.currentTime%60)<10)?("0"+Math.trunc(this.$parent.currentTime%60)):(Math.trunc(this.$parent.currentTime%60)));
,
allTime()
return ((Math.trunc(this.$parent.duration/60)<10)?("0"+Math.trunc(this.$parent.duration/60)):(Math.trunc(this.$parent.duration/60)))+":"+((Math.trunc(this.$parent.duration%60)<10)?("0"+Math.trunc(this.$parent.duration%60)):(Math.trunc(this.$parent.duration%60)));
,mounted()
this.songName = this.$parent.songNames[this.$parent.index].name;
this.changeSlideTime();
</script>
<style scoped>
/* 关于播放器的样式 */
.music
width: 100%;
height: 120px;
background: black;
/* 相对浏览器定位 */
position: fixed;
left: 0px;
bottom: 0px;
/* bottom: 100px; */
/* border-bottom: 50px; */
/* 透明度 */
opacity: 0.8;
/* 阴影值 */
box-shadow: 10px 15px 15px 1px black
.music .m_hold
float: left;
width: 90px;
height: 90px;
/* 调整音乐盒图片 */
.music .m_img
margin-top: 15px;
margin-left: 10px;
margin-right: 10px;
/* 左浮动 */
float: left;
width: 90px;
height: 90px;
border-radius: 50%;
overflow: hidden;
/* 修改文字 */
.music .m_text
/* 左浮动 */
float: left;
color: white;
font-size: 20px;
/* 字体加粗 */
font-weight: bold;
margin-top: 25px;
margin-left: 20px;
margin-bottom: 10px;
width: 25%;
/* 使得所有a标签一起移动 */
.music .m_btn
float: left;
position: absolute;
/* 绝对定位:防止歌曲名称过长,挤出div */
left: 48%;
/* 修改a标签 */
.music .m_btn a
width: 32px;
height: 32px;
float: left;
margin-top: 50px;
margin-left: 20px;
background: url(@/assets/player_bg.png);
.music .m_btn .m_prev
background-position: -69px 0px;
.music .m_btn .m_next
background-position: -150px 0px;
.music .m_btn .m_play
background-position: -107px -5px;
.music .m_btn .m_prev:hover
background-position: -69px -32px;
.music .m_btn .m_next:hover
background-position: -150px -32px;
.music .m_btn .m_play:hover
background-position: -107px -47px;
.music .m_btn .m_pause
background-position: -292px -94px;
.music .m_btn .m_pause:hover
background-position: -334px -94px;
/* 还有一个悬停 没写 */
/* 设置最右边的关闭样式 */
.music .m_close
float: right;
background: white;
cursor: pointer;
width: 23px;
height: 100px;
margin-top: 10px;
background: url(@/assets/player_bg.png);
.m_time
width: 100px;
height: 20px;
margin-top: 64px;
float:left;
margin-left: 10px;
font:bold
/* 设置最右边的关闭样式 */
.music_hide
float: left;
background: white;
cursor: pointer;
width: 23px;
height: 100px;
margin-top: 2px;
.go
animation: bounce-in 2s linear infinite;
.come
animation: none;
@keyframes bounce-in
from
transform: rotate(0deg);
to
transform: rotate(360deg);
.open-enter-active
animation: slide-in linear 0.5s;
.open-leave-active
animation: slide-in reverse linear 0.5s;
@keyframes slide-in
from
transform: translateX(-100%);
to
transform: translateX(0%);
</style>
HidePlayer.vue
<template>
<div class="music_hide" @click="changeCloseState()"><a href="#" class="m_open"></a></div>
</template>
<script>
export default
name:HidePlayer,
methods:
changeCloseState()
this.$emit("hello");
</script>
<style scoped>
.music_hide
float: left;
background: url(@/assets/player_bg.png);
cursor: pointer;
width: 23px;
height: 100px;
margin-top: 10px;
bottom: 0px;
/* bottom: 100px; */
position: fixed;
background-position-x: -45px;
</style>
总结
真可谓是基础不牢,地动山摇,由于CSS,JS学的很浅,现在很多的布局搞不明白,布局效果只有一点点的尝试,导致自己的开发进度变得特别特别缓慢,再次提醒各位C友,一定一定要注重基础的深入学习。勉之哉!!
以上是关于Vue开发历程---音乐播放器的继续的主要内容,如果未能解决你的问题,请参考以下文章
七夕活动_一个移动鼠标播放告白气球的Python程序(2022年8月可用)
Android-嵌入式蓝牙 多年蓝牙产品开发学习心路历程分享-A2DP音频流的建立A2DP播放暂停音乐命令交互HFPAVRCPRFCOMMOPPAVDTP