简单音乐播放器html+css+基础vue+含源码,有搜索和播放mv功能,代码可直接复制用。
题目:html+css+基础vue实现的简单音乐播放器(含源码),有搜索和播放mv功能,代码可直接复制用。问题描述:如果vue刚入门,掌握一些基础语法后就可以写一个简单的音乐播放器来练练手~~如果没学vue,也可以看看,体验下vue的人门。代码直接复制就能运行。这里详细说了html与css的布局,与vue基础的使用先看效果:代码实现:...
·
题目:html+css+基础vue实现的简单音乐播放器(含源码),有搜索和播放mv功能,代码可直接复制用。
问题描述:
如果vue刚入门,掌握一些基础语法后就可以写一个简单的音乐播放器来练练手~~如果没学vue,也可以看看,体验下vue的人门。代码直接复制就能运行。
这里详细说了html与css的布局,与vue基础的使用
先看效果:
1.基础界面样式布局
2.搜素歌曲(比如搜赵雷)
3.播放歌曲,点击各个歌曲前面那个小圆圈就能播放
4.播放mv,有mv的歌曲会在后面有一个mv按钮,点击就能播放
代码实现:
一.html布局
<div class="kuang" id="player">
<img src="image/yinyue.png" alt="xxx" class="yinyue1" title="欢迎你~">
<img src="image/yinyue2.png" alt="xxx" class="yinyue2" title="欢迎你~">
<div class="ding">
<input type="text" class="shousuo" autocomplete="off" v-model='query' @keyup.enter="searchMusic();" /> <input
type="button" class="anniu" @click="searchMusic();">
</div>
<!-- 歌曲列表 -->
<div class="yingcang">
<div class="zuo">
<ul class="zuo1">
<li v-for="item in musicList">
<a href="javascript:;" @click='playMusic(item.id)'></a>
{{item.name}}
<a href="javascript:;" @click='playMv(item.mvid)' v-if="item.mvid!=0"></a>
</li>
</ul>
</div>
</div>
<img src="image/line.png" alt="xxx" class="xian2">
<img src="image/player_bar.png" alt="" class="gan" :class="{playing:isPlay}">
<div class="tu" :class="{active:isActive}">
<img src="image/disc.png" alt="" width="100%" height="100%" class="tu2">
<img :src="coverUrl" alt="" width="100%" height="100%" class="tu3">
</div>
<div class="line"><img src="image/line.png" alt="" width="100%" height="100%"></div>
<audio :src="musicUrl" ref='audio' @play="play" @pause="pause" controls autoplay loop class="xia"></audio>
<div class="tishi">
<h3>提示</h3>
<p style="margin-top: 10px;">  如果点击了无法播放,可能是该歌曲曲源缺失。可以点击其它歌曲播放。切歌时切勿过于频繁,否则可能会卡。</p>
</div>
<!-- 评论 -->
<h2 class="liuyan">热门评论</h2>
<div class="sanjiao"></div>
<div class="yingcang2">
<div class="pinglun">
<div class="pinglun1" v-for="item in hotComments">
<img :src="item.user.avatarUrl" alt="" width="50px" height="50px"
style="float: left; margin-left: 2px; border-radius: 50%;">
<h3 class="neirong1">{{item.user.nickname}}</h3>
<p class="neirong2">   {{ item.content}}</p>
</div>
</div>
</div>
<!-- 视频 -->
<video :src="mvUrl" controls="controls" v-show="showVideo" ref='video' class="shiping" autoplay="autoplay"
loop="loop"></video>
<img src="image/guanbi.png" alt="X" width="20px" height="20px" title="关闭视频" v-show="showVideo" @click="closeMv"
style="position: absolute; top: 10px;right: 10px; z-index: 22; cursor: pointer; ">
</div>
注意:定义了一个最大的父盒子class叫“kuang”。里面有些布局用到的图片得换成自己的。要效果展示的图片素材可以留言。
如果里面图片没换成自己的,效果如下,但是不影响运行,把相应图片链接放上相应的img标签里去就行。
照样能放歌曲。
二.css布局
.kuang{
position: relative;
margin: 0 auto;
width: 800px;
height: 544px;
border-radius: 10px;
background-color: rgba(252, 248, 248, 0.7);
}
.yinyue1{
position: absolute;
right: -2px;
bottom: 10px;
height: 200px;
width: 230px;
}
.yinyue2{
position: absolute;
top: -105px;
left: -80px;
width: 300px;
height: 180px;
z-index: 21;
}
.ding{
position: absolute;
top:0px;
left:0px;
width: 800px;
height: 60px;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
background: #55b9f3;
box-shadow: inset 34px 34px 68px #316b8d,
inset -34px -34px 68px #79ffff;
z-index: 11;
}
.shousuo{
position: absolute;
top: 15px;
right: 50px;
height: 30px;
width: 270px;
border: none;
outline: none;
padding-left: 15px;
border-top-left-radius: 15px;
border-bottom-left-radius: 15px;
background-color: rgba(252, 248, 248, 0.7);
}
.anniu{
position: absolute;
top: 15px;
right: 20px;
height: 30px;
width: 30px;
border: none;
outline: none;
background-image: url(../image/shousuo.jfif);
background-size: 100% 100%;
cursor: pointer;
border-top-right-radius: 15px;
border-bottom-right-radius: 15px;
}
.zuo{
position: absolute;
top:0px;
left:0px;
width: 200px;
height: 450px;
overflow: auto;
}
.yingcang{
position: absolute;
top: 60px;
left:0px;
width: 165px;
height: 450px;
overflow: hidden;
}
.xian2{
position: absolute;
top: 50px;
left:165px;
height: 500px;
width: 2px;
}
.zuo li{
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-left: 0px;
width: 165px;
height: 40px;
line-height: 40px;
text-indent: 5px;
font-size: 15px;
font-family: 'fangsong';
font-weight: bold;
}
.zuo1 li:nth-of-type(2n-1){
background-color: rgba(252, 248, 248, 0.3);
}
.zuo li a{
padding-left: 5px;
font-family: 'icomoon';
text-decoration: none;
line-height: 40px;
vertical-align: middle;
color: rgb(19, 224, 98);
}
.tu3{
position: absolute;
top: 65px;
left: 65px;
width: 170px;
height: 170px;
border-radius: 50%;
}
.tu{
position: absolute;
top: 122px;
left: 250px;
width: 300px;
height: 300px;
}
.active{
animation: rotateImg 5s linear infinite;
-webkit-animation: rotateImg 5s linear infinite;
vertical-align: middle;
}
.gan{
position: absolute;
top: 50px;
left: 400px;
width: 100px;
height: 140px;
z-index: 10;
transform-origin: 9% 8%;
transform:rotate(-28deg);
transition: 1s; /* 换成playing属性后是,应该是原有的属性都保持不变,只是覆盖的变 */
}
.playing{
transform-origin: 9% 8%;
transform:rotate(1deg);
transition: all 1s;
}
/* 旋转代码,我也不懂啥意思 */
@keyframes rotateImg {
0% {transform : rotate(0deg);}
100% {transform : rotate(360deg);}
}
@-webkit-keyframes rotateImg {
0%{-webkit-transform : rotate(0deg);}
100%{-webkit-transform : rotate(360deg);}
}
.line{
position: absolute;
top: 60px;
right: 220px;
width: 1px;
height: 450px;
z-index: 11;
}
.xia{
position: absolute;
bottom: 0px;
left:0px;
width: 800px;
height: 34px;
outline: none;
background-color: rgb(241, 243, 244);
}
.tishi{
position: absolute;
right: 5px;
top: 200px;
width: 210px;
height: 300px;
font-family:'FangSong';
text-align: center;
}
.liuyan{
position: absolute;
top: 88px;
right: 5px;
height: 20px;
width: 65px;
line-height: 20px;
font-size: 15px;
font-family: 'fangsong';
cursor: pointer;
}
.liuyan::after {
position: absolute;
bottom: 0px;
left: 0px;
content: '';
width: 0px;
height: 1px;
background: linear-gradient(to top right, rgb(220, 144, 57), rgb(243, 247, 13), rgb(231, 56, 12));
transition: all 1s ease 0s;
}
.liuyan:hover::after {
width: 100%;
}
.liuyan:hover{
color: rgb(224, 26, 26);
}
.sanjiao{
position: absolute;
right: -10px;
top: 88px;
width: 0;
height: 0;
border-right: 10px rgba(255, 255, 255,.7) solid;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
display: none;
}
.pinglun{
position: absolute;
overflow: auto;
left: 0px;
top: 0px;
height: 450px;
width: 250px;
background-color: rgba(255, 255, 255,.7);
}
.yingcang2{
position: absolute;
overflow: hidden;
right: -220px;
top: 60px;
height: 450px;
width: 210px;
border-radius: 10px;
display: none;
}
.pinglun1{
float: left;
margin-top: 20px;
width: 250px;
}
.neirong1{
float: left;
padding-left: 10px;
white-space:nowrap ;
overflow: hidden;
text-overflow: ellipsis;
width: 150px;
height: 50px;
font-size: 20px;
line-height: 50px;
}
.neirong2{
float: left;
width: 200px;
overflow: hidden;
margin-top: 5px;
padding-left: 5px;
text-align: center;
font-size: 15px;
color: rgba(12, 12, 12,.8);
}
.shiping{
position: absolute;
left: 0px;
bottom: 0px;
width: 800px;
height: 544px;
z-index: 20;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
outline: none;
background-color: rgb(8, 8, 8);
}
三.vue部分,其代码写在script标签里。下面全部代码可以放在body的最底部位置
<script src="js/gonggong.js"></script>
<script src="js/jianjie.js"></script>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 官网提供的 axios 在线地址 -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script type="text/javascript">
// 设置axios的基地址
axios.defaults.baseURL = 'https://autumnfish.cn';
// axios.defaults.baseURL = 'http://localhost:3000';
// 实例化vue
var app = new Vue({
el: "#player",
data: {
// 搜索关键字
query: '',
// 歌曲列表
musicList: [],
// 歌曲url
musicUrl: '',
// 是否正在播放
isPlay: false,
isActive: false,
/* 歌曲封面 */
coverUrl: 'image/Snipaste_2020-08-04_13-48-03.png',
// 歌曲热门评论
hotComments: [],
/* 视频播放 */
showVideo: false,
/* mv地址 */
mvUrl: ''
},
// 方法
methods: {
// 搜索歌曲
searchMusic() {
if (this.query == 0) {
return
}
axios.get('/search?keywords=' + this.query).then(response => {
// 保存内容
this.musicList = response.data.result.songs;
})
// 清空搜索
this.query = ''
},
// 播放歌曲
playMusic(musicId) {
// 获取歌曲url
axios.get('/song/url?id=' + musicId).then(response => {
// 保存歌曲url地址
this.musicUrl = response.data.data[0].url
})
// 获取歌曲封面
axios.get('/song/detail?ids=' + musicId).then(response => {
// console.log(response)
// 设置封面
this.coverUrl = response.data.songs[0].al.picUrl
})
// 获取歌曲热门评论
axios.get('/comment/hot?type=0&id=' + musicId).then(response => {
// console.log(response)
// 保存热门评论
this.hotComments = response.data.hotComments
})
},
// audio的play事件
play() {
this.isPlay = true
this.isActive = true
},
// audio的pause事件
pause() {
this.isPlay = false
this.isActive = false
},
// 播放mv
playMv(vid) {
if (vid) {
this.showVideo = true;
// 获取mv信息
axios.get('/mv/url?id=' + vid).then(response => {
// console.log(response)
// 暂停歌曲播放
this.$refs.audio.pause()
// 获取mv地址
this.mvUrl = response.data.data.url
})
}
},
closeMv() {
this.showVideo = false
this.$refs.video.pause()
},
},
})
//下面是控制查看评论功能界面的显示隐藏,用得是基础的js语句
var liuyan = document.querySelector('.liuyan');
var sanjiao = document.querySelector('.sanjiao');
var pinglun = document.querySelector('.yingcang2');
var temp = 0;
liuyan.addEventListener('click', function (e) {
if (temp == 0) {
sanjiao.style.display = 'block';
pinglun.style.display = 'block';
temp = 1;
} else if (temp == 1) {
sanjiao.style.display = 'none';
pinglun.style.display = 'none';
temp = 0;
}
})
</script>
下面是一套完整的源码,建一个.html文件,然后直接复制粘贴就能用看到效果。(把图片换成自己的地址就行)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>在线音乐播放器</title>
<link rel="stylesheet" href="css/zaixian.css">
<link rel="stylesheet" href="css/gonggong.css">
<style>
.kuang{
position: relative;
margin: 0 auto;
width: 800px;
height: 544px;
border-radius: 10px;
background-color: rgba(252, 248, 248, 0.7);
}
.yinyue1{
position: absolute;
right: -2px;
bottom: 10px;
height: 200px;
width: 230px;
}
.yinyue2{
position: absolute;
top: -105px;
left: -80px;
width: 300px;
height: 180px;
z-index: 21;
}
.ding{
position: absolute;
top:0px;
left:0px;
width: 800px;
height: 60px;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
background: #55b9f3;
box-shadow: inset 34px 34px 68px #316b8d,
inset -34px -34px 68px #79ffff;
z-index: 11;
}
.shousuo{
position: absolute;
top: 15px;
right: 50px;
height: 30px;
width: 270px;
border: none;
outline: none;
padding-left: 15px;
border-top-left-radius: 15px;
border-bottom-left-radius: 15px;
background-color: rgba(252, 248, 248, 0.7);
}
.anniu{
position: absolute;
top: 15px;
right: 20px;
height: 30px;
width: 30px;
border: none;
outline: none;
background-image: url(../image/shousuo.jfif);
background-size: 100% 100%;
cursor: pointer;
border-top-right-radius: 15px;
border-bottom-right-radius: 15px;
}
.zuo{
position: absolute;
top:0px;
left:0px;
width: 200px;
height: 450px;
overflow: auto;
}
.yingcang{
position: absolute;
top: 60px;
left:0px;
width: 165px;
height: 450px;
overflow: hidden;
}
.xian2{
position: absolute;
top: 50px;
left:165px;
height: 500px;
width: 2px;
}
.zuo li{
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-left: 0px;
width: 165px;
height: 40px;
line-height: 40px;
text-indent: 5px;
font-size: 15px;
font-family: 'fangsong';
font-weight: bold;
}
.zuo1 li:nth-of-type(2n-1){
background-color: rgba(252, 248, 248, 0.3);
}
.zuo li a{
padding-left: 5px;
font-family: 'icomoon';
text-decoration: none;
line-height: 40px;
vertical-align: middle;
color: rgb(19, 224, 98);
}
.tu3{
position: absolute;
top: 65px;
left: 65px;
width: 170px;
height: 170px;
border-radius: 50%;
}
.tu{
position: absolute;
top: 122px;
left: 250px;
width: 300px;
height: 300px;
}
.active{
animation: rotateImg 5s linear infinite;
-webkit-animation: rotateImg 5s linear infinite;
vertical-align: middle;
}
.gan{
position: absolute;
top: 50px;
left: 400px;
width: 100px;
height: 140px;
z-index: 10;
transform-origin: 9% 8%;
transform:rotate(-28deg);
transition: 1s; /* 换成playing属性后是,应该是原有的属性都保持不变,只是覆盖的变 */
}
.playing{
transform-origin: 9% 8%;
transform:rotate(1deg);
transition: all 1s;
}
/* 旋转代码,我也不懂啥意思 */
@keyframes rotateImg {
0% {transform : rotate(0deg);}
100% {transform : rotate(360deg);}
}
@-webkit-keyframes rotateImg {
0%{-webkit-transform : rotate(0deg);}
100%{-webkit-transform : rotate(360deg);}
}
.line{
position: absolute;
top: 60px;
right: 220px;
width: 1px;
height: 450px;
z-index: 11;
}
.xia{
position: absolute;
bottom: 0px;
left:0px;
width: 800px;
height: 34px;
outline: none;
background-color: rgb(241, 243, 244);
}
.tishi{
position: absolute;
right: 5px;
top: 200px;
width: 210px;
height: 300px;
font-family:'FangSong';
text-align: center;
}
.liuyan{
position: absolute;
top: 88px;
right: 5px;
height: 20px;
width: 65px;
line-height: 20px;
font-size: 15px;
font-family: 'fangsong';
cursor: pointer;
}
.liuyan::after {
position: absolute;
bottom: 0px;
left: 0px;
content: '';
width: 0px;
height: 1px;
background: linear-gradient(to top right, rgb(220, 144, 57), rgb(243, 247, 13), rgb(231, 56, 12));
transition: all 1s ease 0s;
}
.liuyan:hover::after {
width: 100%;
}
.liuyan:hover{
color: rgb(224, 26, 26);
}
.sanjiao{
position: absolute;
right: -10px;
top: 88px;
width: 0;
height: 0;
border-right: 10px rgba(255, 255, 255,.7) solid;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
display: none;
}
.pinglun{
position: absolute;
overflow: auto;
left: 0px;
top: 0px;
height: 450px;
width: 250px;
background-color: rgba(255, 255, 255,.7);
}
.yingcang2{
position: absolute;
overflow: hidden;
right: -220px;
top: 60px;
height: 450px;
width: 210px;
border-radius: 10px;
display: none;
}
.pinglun1{
float: left;
margin-top: 20px;
width: 250px;
}
.neirong1{
float: left;
padding-left: 10px;
white-space:nowrap ;
overflow: hidden;
text-overflow: ellipsis;
width: 150px;
height: 50px;
font-size: 20px;
line-height: 50px;
}
.neirong2{
float: left;
width: 200px;
overflow: hidden;
margin-top: 5px;
padding-left: 5px;
text-align: center;
font-size: 15px;
color: rgba(12, 12, 12,.8);
}
.shiping{
position: absolute;
left: 0px;
bottom: 0px;
width: 800px;
height: 544px;
z-index: 20;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
outline: none;
background-color: rgb(8, 8, 8);
}
</style>
</head>
<body>
<div class="kuang" id="player">
<img src="image/yinyue.png" alt="xxx" class="yinyue1" title="欢迎你~">
<img src="image/yinyue2.png" alt="xxx" class="yinyue2" title="欢迎你~">
<div class="ding">
<input type="text" class="shousuo" autocomplete="off" v-model='query' @keyup.enter="searchMusic();" /> <input
type="button" class="anniu" @click="searchMusic();">
</div>
<!-- 歌曲列表 -->
<div class="yingcang">
<div class="zuo">
<ul class="zuo1">
<li v-for="item in musicList">
<a href="javascript:;" @click='playMusic(item.id)'></a>
{{item.name}}
<a href="javascript:;" @click='playMv(item.mvid)' v-if="item.mvid!=0"></a>
</li>
</ul>
</div>
</div>
<img src="image/line.png" alt="xxx" class="xian2">
<img src="image/player_bar.png" alt="" class="gan" :class="{playing:isPlay}">
<div class="tu" :class="{active:isActive}">
<img src="image/disc.png" alt="" width="100%" height="100%" class="tu2">
<img :src="coverUrl" alt="" width="100%" height="100%" class="tu3">
</div>
<div class="line"><img src="image/line.png" alt="" width="100%" height="100%"></div>
<audio :src="musicUrl" ref='audio' @play="play" @pause="pause" controls autoplay loop class="xia"></audio>
<div class="tishi">
<h3>提示</h3>
<p style="margin-top: 10px;">  如果点击了无法播放,可能是该歌曲曲源缺失。可以点击其它歌曲播放。切歌时切勿过于频繁,否则可能会卡。</p>
</div>
<!-- 评论 -->
<h2 class="liuyan">热门评论</h2>
<div class="sanjiao"></div>
<div class="yingcang2">
<div class="pinglun">
<div class="pinglun1" v-for="item in hotComments">
<img :src="item.user.avatarUrl" alt="" width="50px" height="50px"
style="float: left; margin-left: 2px; border-radius: 50%;">
<h3 class="neirong1">{{item.user.nickname}}</h3>
<p class="neirong2">   {{ item.content}}</p>
</div>
</div>
</div>
<!-- 视频 -->
<video :src="mvUrl" controls="controls" v-show="showVideo" ref='video' class="shiping" autoplay="autoplay"
loop="loop"></video>
<img src="image/guanbi.png" alt="X" width="20px" height="20px" title="关闭视频" v-show="showVideo" @click="closeMv"
style="position: absolute; top: 10px;right: 10px; z-index: 22; cursor: pointer; ">
</div>
<script src="js/gonggong.js"></script>
<script src="js/jianjie.js"></script>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 官网提供的 axios 在线地址 -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script type="text/javascript">
// 设置axios的基地址
axios.defaults.baseURL = 'https://autumnfish.cn';
// axios.defaults.baseURL = 'http://localhost:3000';
// 实例化vue
var app = new Vue({
el: "#player",
data: {
// 搜索关键字
query: '',
// 歌曲列表
musicList: [],
// 歌曲url
musicUrl: '',
// 是否正在播放
isPlay: false,
isActive: false,
/* 歌曲封面 */
coverUrl: 'image/Snipaste_2020-08-04_13-48-03.png',
// 歌曲热门评论
hotComments: [],
/* 视频播放 */
showVideo: false,
/* mv地址 */
mvUrl: ''
},
// 方法
methods: {
// 搜索歌曲
searchMusic() {
if (this.query == 0) {
return
}
axios.get('/search?keywords=' + this.query).then(response => {
// 保存内容
this.musicList = response.data.result.songs;
})
// 清空搜索
this.query = ''
},
// 播放歌曲
playMusic(musicId) {
// 获取歌曲url
axios.get('/song/url?id=' + musicId).then(response => {
// 保存歌曲url地址
this.musicUrl = response.data.data[0].url
})
// 获取歌曲封面
axios.get('/song/detail?ids=' + musicId).then(response => {
// console.log(response)
// 设置封面
this.coverUrl = response.data.songs[0].al.picUrl
})
// 获取歌曲热门评论
axios.get('/comment/hot?type=0&id=' + musicId).then(response => {
// console.log(response)
// 保存热门评论
this.hotComments = response.data.hotComments
})
},
// audio的play事件
play() {
this.isPlay = true
this.isActive = true
},
// audio的pause事件
pause() {
this.isPlay = false
this.isActive = false
},
// 播放mv
playMv(vid) {
if (vid) {
this.showVideo = true;
// 获取mv信息
axios.get('/mv/url?id=' + vid).then(response => {
// console.log(response)
// 暂停歌曲播放
this.$refs.audio.pause()
// 获取mv地址
this.mvUrl = response.data.data.url
})
}
},
closeMv() {
this.showVideo = false
this.$refs.video.pause()
},
},
})
var liuyan = document.querySelector('.liuyan');
var sanjiao = document.querySelector('.sanjiao');
var pinglun = document.querySelector('.yingcang2');
var temp = 0;
liuyan.addEventListener('click', function (e) {
if (temp == 0) {
sanjiao.style.display = 'block';
pinglun.style.display = 'block';
temp = 1;
} else if (temp == 1) {
sanjiao.style.display = 'none';
pinglun.style.display = 'none';
temp = 0;
}
})
</script>
</body>
</html>
总结
播放器是较简单的,如有不好的地方望见谅。基本这样就可以使用了,有什么问题建议可以留言一起交流学习。
更多推荐
已为社区贡献9条内容
所有评论(0)