首页 > 其他分享 >Vue开发历程---音乐播放器

Vue开发历程---音乐播放器

时间:2022-10-30 22:31:15浏览次数:91  
标签:播放器 返回 Vue assets 音频 --- music background png

 


前言

浅浅记录一下自己开发音乐播放器的历程,巩固自己的所学。同时也是深感基础不牢,地动山摇。


一、audio标签的使用

1、Audio 对象属性

属性

描述

audioTracks

返回表示可用音频轨道的 AudioTrackList 对象。

autoplay

设置或返回是否在就绪(加载完成)后随即播放音频。

buffered

返回表示音频已缓冲部分的 TimeRanges 对象。

controller

返回表示音频当前媒体控制器的 MediaController 对象。

controls

设置或返回音频是否应该显示控件(比如播放/暂停等)。

crossOrigin

设置或返回音频的 CORS 设置。

currentSrc

返回当前音频的 URL。

currentTime

设置或返回音频中的当前播放位置(以秒计)。

defaultMuted

设置或返回音频默认是否静音。

defaultPlaybackRate

设置或返回音频的默认播放速度。

duration

返回音频的长度(以秒计)。

ended

返回音频的播放是否已结束。

error

返回表示音频错误状态的 MediaError 对象。

loop

设置或返回音频是否应在结束时再次播放。

mediaGroup

设置或返回音频所属媒介组合的名称。

muted

设置或返回是否关闭声音。

networkState

返回音频的当前网络状态。

paused

设置或返回音频是否暂停。

playbackRate

设置或返回音频播放的速度。

played

返回表示音频已播放部分的 TimeRanges 对象。

preload

设置或返回音频的 preload 属性的值。

readyState

返回音频当前的就绪状态。

seekable

返回表示音频可寻址部分的 TimeRanges 对象。

seeking

返回用户当前是否正在音频中进行查找。

src

设置或返回音频的 src 属性的值。

textTracks

返回表示可用文本轨道的 TextTrackList 对象。

volume

设置或返回音频的音量。

2、对象方法

方法

描述

addTextTrack()

向音频添加新的文本轨道。

canPlayType()

检查浏览器是否能够播放指定的音频类型。

fastSeek()

在音频播放器中指定播放时间。

getStartDate()

返回新的 Date 对象,表示当前时间线偏移量。

load()

重新加载音频元素。

play()

开始播放音频。

pause()

暂停当前播放的音频。

二、效果

效果如下:

Vue开发历程---音乐播放器_Vue

三、代码

代码如下: MusicPlayer.vue

<template>
<div class="music">
<!-- 占位 -->
<div class="m_hold">

</div>
<div class="m_img">
<img :src="this.$parent.songNames[this.$parent.index].png" width="90px" :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="value1"></el-slider>
</div>
</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: '',
value1: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
}
},
watch:
{


}, mounted() {
this.songName = this.$parent.songNames[this.$parent.index].name
}

}
</script>

<style scoped>
/* 关于播放器的样式 */
.music {
width: 100%;
height: 120px;
background: black;
/* 相对浏览器定位 */
position: absolute;
left: 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: 40%;
}

/* 修改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);

}

/* 设置最右边的关闭样式 */
.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>

HideMusic.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: 100px;
position: absolute;
background-position-x: -45px;
}
</style>

MyPlayer.vue

<template>
<div>
<transition name="open" mode="out-in">
<component v-bind:is="view" @hello="changeSlideState" @play="changePlayState" @lastSongs="lastSongs"
@nextSongs="nextSongs"></component>
</transition>
<audio class="m_mp3" id="m_mp3" :src="this.songNames[this.index].Url" autoplay loop>

</audio>
</div>

</template>

<script>
import HidePlayer from '@/part/HidePlayer'
import MusicPlayer from '@/part/MusicPlayer'
export default {
name: 'MyPlayer',
data() {
return {
view: MusicPlayer,
isClose: false,
isShow: true,
isRun: 'come',
index: 0,
songNum: 2,
currentTime: '0:00',
duration: '0:00',
songNames: [
{
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;
}

}
}, mounted() {
this.songNum = this.songNames.length;

}

}
</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>

四、难点解析


1、过渡动画的实现

Vue开发历程---音乐播放器_Vue_02

参考了vue文档过渡&动画中多个组件的过渡(下面三份代码)。​​vue文档​

<transition name="component-fade" mode="out-in">
<component v-bind:is="view"></component>
</transition>
new Vue({
el: '#transition-components-demo',
data: {
view: 'v-a'
},
components: {
'v-a': {
template: '<div>Component A</div>'
},
'v-b': {
template: '<div>Component B</div>'
}
}
})
.component-fade-enter-active, .component-fade-leave-active {
transition: opacity .3s ease;
}
.component-fade-enter, .component-fade-leave-to
/* .component-fade-leave-active for below version 2.1.8 */ {
opacity: 0;
}

因此分化出MusicPlayer.vue 和 HideMusic.vue,由此又产生了组件内通信的问题。

2、组件内通信

Vue开发历程---音乐播放器_ide_03

为什么会产生组件内的通信?原因在于:MusicPlayer组件和HidePlayer组件,只能有一个展示,但是在不展示的过程中,他的数据应该也是实时改变的。例如MusicPlayer组件上有播放按钮,如果不采用组件通信,那么MusicPlayer重新渲染的时候,播放按钮会回到最初的设定,是不符合逻辑的。所以需要采用组件内通信的方式。实现的方式也比较简单,子组件直接访问父组件的数据,子组件通过$emit调用父组件的方法,修改父组件的数据。

3、旋转动画的实现

Vue开发历程---音乐播放器_音频播放_04

首先,编写动画。

.go {
animation: bounce-in 2s linear infinite;
}

.come {
animation: none;
}

@keyframes bounce-in {
from {
transform: rotate(0deg);
}

to {
transform: rotate(360deg);
}
}

然后,动态绑定class,isRun两个值即为"go","come"。

<div class="m_img">
<img :src="this.$parent.songNames[this.$parent.index].png" width="90px" :class="this.$parent.isRun">
</div>

总结

这次一个小小的实战,让我重新学习到了不少的CSS操作方法,但由于基础太弱,很多简单的东西都变得复杂。还好vue提供了一些方法,让解决方式变得容易了一些。奋斗吧!还有很长的路要走!!

标签:播放器,返回,Vue,assets,音频,---,music,background,png
From: https://blog.51cto.com/u_15807146/5807883

相关文章

  • [CSP-S 2022] 星战
    link首先手玩一下满足条件的图,只需要满足条件二:所有点出度为1,条件1会自然满足,我们必然可以顺着其出边走下去。code......
  • vue项目以及element-ui国际化的基本实战
    背景有的时候我们做的项目需要支持切换多国语言,那么我们就需要使用到vue-i18n插件使用步骤注意:下面操作是基于vue2的版本实现功能:在vue单文件组件中如何使用模版......
  • Vue 尚硅谷 axios
     安装npmiaxios跨域:1.cors2.jsonpscriptsrc解决get请求。post,delete,put无法请求3.代理vue-clivue.config.js vue-cli代理缺点:1.不能配置多个代理2.......
  • CSP-S2022
    luogu上还是240,和出考场时的估分差不多,不算很理想(感觉上考场一紧张代码能力直线下降。上来T1,T2都是一眼看出做法,但调代码花了很久,到16:30左右才顺利过完所有数据。然后......
  • 计算、监听属性与组件化开发与vue-cli
    计算属性1.如果使用{{函数()}},每次页面刷新函数都会执行,会很消耗资源,如果放在computed中,只有变量发生变化,他才重新运算,使用时不需要加括号,{{属性}}即可2.实例<!DOCTYPE......
  • 【Vue3】watch 监听器的使用
    watch的三个参数watch第一个参数,监听源watch第二个参数,回调函数cb(newVal,oldVal)watch第三个参数,一个options配置项是一个对象{immediate:true//是否......
  • vue-admin-template快速开发框架,菜单栏不显示层级结构
    问题现象路由页面效果解决办法路由添加中配置alwaysShow:true,//树形层级显示页面效果......
  • Vue表单输入绑定、组件、插槽的使用(三)
    一、表单输入绑定<!DOCTYPEhtml><html> <head> <metacharset="utf-8"> <title></title> <linkrel="stylesheet"href="https://stackpath.bootstrapcdn.com/bo......
  • 「测试开发全栈-HTML」(9)css字体属性之字体粗细和样式
    昨天说了CSS字体属性的大小,font-family,今天我们来一起学习下字体属性的字体粗细font-weight  还是使用昨天的那首诗,让诗句中的最后一句显示粗体,看下效果:可以看到最后......
  • 解决swagger2 --> Illegal DefaultValue null for parameter type integer 保存问题
    在pmo.xml中加入两个依赖<!--增加两个配置--><dependency> <groupId>io.swagger</groupId> <artifactId>swagger-annotations</artifactId> <version>${swagger-mode......