七、VUE基础——悦听音乐播放器案例(vue+axios)
在b站看完vue教程的悦听音乐播放器案例,有很大的收获,这里自己总结一下,由于之前不太理解弹性盒子的知识,又去b站看了另一位老师的课,也将其所给的资源下载下来发布在博客中:弹性盒子flex首先对界面功能进行分析,从上到下是搜索栏、主体部分、音频播放进度条;其中主体部分昨从到右分为音乐播放列表、黑胶碟片的歌曲图片、留言列表。一、功能总结歌曲搜索:输入歌曲的相关内容按回车键搜索数据;具体步骤为按下回车
在b站看完vue教程的悦听音乐播放器案例,有很大的收获,这里自己总结一下,由于之前不太理解弹性盒子的知识,又去b站看了另一位老师的课,也将其所给的资源下载下来发布在博客中:弹性盒子flex
首先对界面功能进行分析,从上到下是搜索栏、主体部分、音频播放进度条;其中主体部分昨从到右分为音乐播放列表、黑胶碟片的歌曲图片、留言列表。
mv播放:
注意:引入vue和axios的js文件时,需要在最后引入,否则数据渲染不出来
vue中定义data中的数据的时候记得是数据名:数据!!!!每次都写成等号报错!
一、功能总结
- 歌曲搜索:输入歌曲的相关内容按回车键搜索数据;具体步骤为按下回车-->查询数据-->渲染数据
- 歌曲播放:点击音乐列表前的红色按键播放音乐;具体步骤为点击按钮-->获取歌曲地址-->歌曲地址绑定(v-bind)
- 歌曲封面:点击音乐播放后音乐的黑胶封面会变成相应歌曲的封面;具体步骤为点击播放歌曲->获取歌曲封面->歌曲封面绑定
- 歌曲评论:点击音乐播放按钮后音乐的热评数据会渲染到界面上;具体步骤为点击播放歌曲->歌曲评论获取(接口 歌曲id)->歌曲评论渲染
- 播放动画:在音乐播放时,黑胶碟片转动,在音乐暂停时,黑胶碟片停止转动;具体步骤为监听音乐播放(v-on play)->监听音乐暂停(v-on pause)->操纵类名
- mv播放:点击mv播放按钮时,播放音乐的mv,不想看mv时,点击旁边的遮罩层,mv播放界面就会隐藏;具体步骤为mv图标显示(v-if)->mv地址获取(接口 mvid)->遮罩层(v-show v-on)->mv地址设置(v-bind)
二、html结构
html结构不算复杂,但是学习到的东西还是挺多的。废话不多说,上代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>悦听</title>
<link rel="stylesheet" href="css/index.css">
<script src="js/index.js"></script>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script> <!--引入axios-->
</head>
<body>
<div class="wrap">
<!-- 播放器主体区域 -->
<div class="play_wrap" id="player">
<!-- 搜索栏 -->
<div class="search_bar">
<!--悦听标题图片 -->
<img src="images/player_title.png" alt="" />
<!-- 搜索歌曲 -->
<input type="text" autocomplete="off" />
</div>
<!-- 主体部分 -->
<div class="center_con">
<!-- 搜索歌曲列表 -->
<div class='song_wrapper'>
<ul class="song_list">
<li><a href="javascript:;"></a> <b>你好</b> <!----></li>
<li v-for="item in musicList">
<a href="javascript:;" @click="musicPlayer(item.id);musicCover(item.id);musicComments(item.id)"></a> <!--音乐播放按钮-->
<b>{{item.name}}</b> <!--音乐名 -->
<span><i>{{item.mvid}}</i></span> <!--mv播放按钮-->
</li>
</ul>
<!-- 左边分割线图片 -->
<img src="images/line.png" class="switch_btn" alt="">
</div>
<!-- 歌曲信息容器 -->
<div class="player_con playing" >
<img src="images/player_bar.png" class="play_bar" />
<!-- 黑胶碟片图片 -->
<img src="images/disc.png" class="disc autoRotate" />
<!-- 歌曲封面图片 -->
<img src="images/cover.png" class="cover autoRotate" />
</div>
<!-- 评论容器 -->
<div class="comment_wrapper">
<h5 class='title'>热门留言</h5>
<div class='comment_list'>
<ul class="comment">
<li class="comment_li">
<div class="comm_up">
<img class="user_pic" src="images/person.png"/> <!--热评头像-->
<b class="user_nickname"></b><br/>
</div>
<div class="comm_right">
<span class="detail"></span>
</div>
</li>
</ul>
</div>
<!-- 右边分割线图片 -->
<img src="images/line.png" class="right_line">
</div>
</div>
<!-- 播放进度条部分 -->
<div class="audio_con">
<audio src="" class="myaudio" controls autoplay looop></audio>
</div>
<!-- 视频mv -->
<div class="video_con">
<video src="" controls="control">
<div class="mask"> </div>
</video>
</div>
</div>
</div>
</body>
</html>
三、css样式及注解
参考别人的代码,自己边查边学习边写,学习到了css很多之前没学到的东西。
1.css未了解到的内容:
(1).body、p、ul&ol、button、font-size在css中都有默认的设置,具体如下:
- body的margin为8px;
- webkit默认行高18px;height18px;
- 默认font-size16px
- p默认margin是16px 0 16px 0;
- ul和ol有默认的margin-left:40px的padding-left和16px 0 16px 0;
- button有2px的border;我没搞懂为什么button之间有空格;
(2).position属性:
position规定元素的定位类型,任何元素都可以定位,不过绝对定位或固定定位元素会生成一个块级框,而不论该元素本身是什么类型。相对定位元素会相对于它在正常流中的默认位置偏移。
position的默认类型是static,其他具体的position值如下:
值 | 描述 |
---|---|
absolute | 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。 元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。 |
fixed | 生成绝对定位的元素,相对于浏览器窗口进行定位。 元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。 |
relative | 生成相对定位的元素,相对于其正常位置进行定位。 因此,"left:20" 会向元素的 LEFT 位置添加 20 像素。 |
static | 默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。 |
inherit | 规定应该从父元素继承 position 属性的值。 |
(3).z-index属性:
- z-index 属性设置元素的堆叠顺序。拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面。
- z-index可以为负值,z-index=-1,把它理解成一个层叠效果就好了,z-index:-1就是在平面的下面一层。
(4).background属性:
- background 简写属性在一个声明中设置所有的背景属性。
- 如果不设置其中的某个值,也不会出问题,比如 background:#ff0000 url('smiley.gif'); 也是允许的。通常建议使用这个属性,而不是分别使用单个属性,因为这个属性在较老的浏览器中能够得到更好的支持,而且需要键入的字母也更少。
值 | 描述 | CSS |
---|---|---|
规定要使用的背景颜色。 | 1 | |
规定背景图像的位置。 | 1 | |
规定背景图片的尺寸。 | 3 | |
规定如何重复背景图像。 | 1 | |
规定背景图片的定位区域。 | 3 | |
规定背景的绘制区域。 | 3 | |
规定背景图像是否固定或者随着页面的其余部分滚动。 | 1 | |
规定要使用的背景图像。 | 1 | |
inherit | 规定应该从父元素继承 background 属性的设置。 | 1 |
具体参考background属性w3c
(5).css中容易混淆的类使用方式
- 在css中,类名+空格+类名,表示一种前后代关系。即.class1 .class2{}
- 在css中 ,类名+类名,表示一种多类选择器,匹配同时具有这两个类的元素。即.class1.class2{}
- 在html中,class="类名+空格+类名",表示该元素同时拥有两个类。即<div class="class1 class2"></div>
例:
html代码:
<div class="player_con playing" >
<img src="images/player_bar.png" class="play_bar" />
<!-- 黑胶碟片图片 -->
<img src="images/disc.png" class="disc autoRotate" />
<!-- 歌曲封面图片 -->
<img src="images/cover.png" class="cover autoRotate" />
</div>
css代码:
.player_con.playing .disc,.player_con.playing .cover {
animation-play-state: running;
}
其中.player_con.playing代表同时匹配这两个类;
.player_con.playing .disc代表player_con.playing下面的disc类是它们的子类;
.player_con.playing .cover代表player_con.playing下面的cover类是它们的子类;
(6).@keyframs:
通过@keyframs可以创建动画,创建动画的原理是,可以逐渐从一套css样式转化为另一套css样式,在动画过程中,能够多次改变这套 CSS 样式。可以通过百分比来规定改变发生的时间,也可以通过关键字"from"和"to",等价于 0% 和 100%;其中0%是动画开始的时间,100%是动画结束的时间。
语法为:@keyframs 动画名称 {动画的选择器:{样式}}
@keyframes mymove
{
0% {top:0px;}
25% {top:200px;}
50% {top:100px;}
75% {top:200px;}
100% {top:0px;}
}
(7).transform属性:
其作用是旋转div,transform元素可以应用于2D和3D的场景,可以实现元素的旋转、倾斜、移动、缩放功能。具体的transform值参考:菜鸟教程transform使用教程
一个旋转的例子:
@keyframes Rotate { /*使 div 元素匀速向下移动:*/
from {
transform: rotateZ(0); /*规定旋转的角度*/
}
to {
transform: rotateZ(360deg);
}
}
(8).为一个标签设置旋转属性,包括调用以上两个属性transform和@keyframs
html代码:
<!-- 黑胶碟片图片 -->
<img src="images/disc.png" class="disc autoRotate" />
<!-- 歌曲封面图片 -->
<img src="images/cover.png" class="cover autoRotate" />
css代码:
.autoRotate {
animation-name: Rotate; /*为 @keyframes 动画规定一个名称*/
animation-iteration-count: infinite; /*animation-iteration-count 属性定义动画的播放次数。这里是无限次播放*/
animation-play-state: paused; /*animation-play-state 属性规定动画正在运行还是暂停。*/
animation-timing-function: linear; /*规定动画的速度曲线。速度曲线定义动画从一套 CSS 样式变为另一套所用的时间。速度曲线用于使变化更为平滑。*/
animation-duration: 5s; /*animation-duration 属性定义动画完成一个周期所需要的时间,以秒或毫秒计。*/
}
- animation-name: Rotate; ->为 @keyframes 动画规定一个名称;具体查看animation-name具体介绍
- animation-iteration-count: infinite; ->animation-iteration-count 属性定义动画的播放次数。这里是无限次播放;具体查看animation-iteration-count具体介绍
- animation-play-state: paused; -> animation-play-state 属性规定动画正在运行还是暂停。具体查看 animation-play-state具体介绍
- animation-timing-function: linear; ->规定动画的速度曲线。速度曲线定义动画从一套 CSS 样式变为另一套所用的时间。速度曲线用于使变化更为平滑。具体查看 animation-timing-function具体介绍
- animation-duration: 5s; -> animation-duration 属性定义动画完成一个周期所需要的时间,以秒或毫秒计。具体查看animation-duration具体介绍
(9).transition
transition 属性是一个简写属性,用于设置四个过渡属性:
- transition-property
- transition-duration
- transition-timing-function
- transition-delay
具体请看w3c教程transition具体教程
2.css代码
body, /*这些必须要设置,不然设置songlist的时候li左边会有边距*/
ul,
li{
margin: 0px;
padding: 0px;
}
/* 大背景 */
.wrap{
position: fixed;
/* CSS 中 left 是规定元素左边缘的属性,
该属性定义了定位元素左外边距边界与其包含块左边界之间的偏移.
left 也可以作为 float 属性的属性值, 表示元素向左浮动.*/
left: 0;
top: 0;
width: 100%;
height: 100%;
background: url("../images/bg.jpg") no-repeat;
background-size: 100% 100%;
}
/* 悦听音乐的整体轮廓 */
.play_wrap{
width: 800px;
height: 544px;
position: fixed;
top: 50%;
left: 50%;
margin-left: -400px;
margin-top: -272px;
/* background-color: blue; */
}
/* 搜索栏 */
.search_bar{
height: 60px;
background-color: #1eacda;
border-top-left-radius: 4px; /*设置左上边框弧度*/
border-top-right-radius: 4px;
/*弹性盒子布局以下3句 */
display: flex;
align-items: center; /*垂直居中对齐 */
justify-content: space-between; /*水平对齐,并且盒子内的所有item之间都有保留空白 */
position: relative;
z-index: 11; /*z-index 属性设置元素的堆叠顺序。拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面。*/
}
.search_bar img{ /*标题img*/
margin-left: 23px;
}
.search_bar input{
margin-right: 23px;
width: 296px;
height: 34px;
border-radius: 17px;
border: 0px;
background: url("../images/zoom.png") 265px no-repeat rgba(255, 255, 255, 0.45); /* backgound的设置依次为背景图url、margin-left、图片不重复、背景颜色 */
text-indent: 15px; /*将段落的第一行缩进*/
outline: none; /*outline (轮廓)是绘制于元素周围的一条线,位于边框边缘的外围,可起到突出元素的作用。zheli outline:none*/
}
/* 主体内容 */
.center_con {
height: 435px;
background-color: rgba(255, 255, 255, 0.5);
display: flex;
position: relative;
}
/* 歌曲列表 */
.song_wrapper{
width: 200px;
height: 435px;
/* box-sizing: border-box; 规定两个并排的带边框的框 */
padding: 10px;
list-style: none;
position: absolute;
left: 0px;
top: 0px;
z-index: 1;
/* background-color: brown; */
}
.song_list{
width: 200px;
height: 100%;
overflow-y: auto;
overflow-x: hidden;
/* background-color: chocolate; */
}
.song_list::-webkit-scrollbar{ /*滚动条消失,但是可以翻动页面*/
display: none;
}
.song_list li{
width: 100%;
height: 40px;
padding-left: 10px;
font-size: 12px;
color: #333;
margin-bottom: 10px;
display: flex;
align-items: center; /*垂直居中*/
flex-wrap: wrap; /*弹性盒子布局,子项目一行装不下,会正序多行显示*/
/* background-color: blueviolet; */
}
.song_list li:nth-child(odd) {/*规定属于其父元素的第奇数个元素的背景色;odd为奇数,even为偶数,这里的括号中也可以传入具体的数字*/
background-color: rgba(240, 240, 240, 0.3);
}
.song_list li a{ /*播放的按钮图片*/
width: 17px;
height: 17px;
display: block;
background-image: url("../images/play.png");
background-size: 100%;
margin-right: 5px;
}
.song_list li b{ /*歌名*/
width: 122px;
font-weight: normal;
/* 以下三行是实现单行文本溢出显示为省略号 */
overflow: hidden;
text-overflow: ellipsis; /*单行文本溢出显示省略号*/
white-space: nowrap;
float: left;
/* background-color: darkcyan; */
}
/* 为显示mv播放按钮预留空间 */
.song_list li span {
width: 23px;
height: 17px;
padding-left: 20px;
}
/* mv视频播放按钮图片样式 */
.song_list li span i {
display: block;
/* width: 100%; */
height: 100%;
cursor: pointer;
background-color: blue;
/* background: url("../images/table.png");
background-repeat: no-repeat; */
background: url("../images/table.png") left -48px no-repeat;
}
/*歌曲信息,即黑胶碟片 */
.player_con{
width: 400px;
height: 435px;
position: absolute;
left: 200px;
top: 0px;
}
.disc{
position: absolute;
left: 73px;
top: 60px;
z-index: 9; /*z-index值大会在上层*/
}
.cover{
position: absolute;
left: 125px;
top: 112px;
width: 150px;
height: 150px;
border-radius: 75px; /*将图片变成圆形*/
z-index: 8;
}
/* 评论容器 */
.comment_wrapper{
width: 180px;
height: 435px;
list-style: none;
position: absolute;
left: 600px;
top: 0px;
padding: 25px 10px;
}
.title { /*.类名 空格 .类名表示一种前后代关系*/
position: absolute;
top: 0;
/* margin-top: 10px;
margin-bottom: 10px; */
}
.comm_up{
margin-top: 20px;
}
.comment_list{
height: 415px;
overflow-y: auto;
overflow-x: hidden;
}
.user_pic{
width: 40px;
height: 40px;
border-radius: 50%;
}
.comm_right{
margin: 10px;
}
.user_comm{ /*评论内容细节样式*/
font-size: 12px;
color: #666;
}
.comment_list::-webkit-scrollbar{ /*滚动条消失,但是可以翻动页面*/
display: none;
}
.user_nickname{
padding-top: -30px;
font-size: 12px;
}
/* 旋转的动画 */
@keyframes Rotate { /*使 div 元素匀速向下移动:*/
from {
transform: rotateZ(0); /*规定旋转的角度*/
}
to {
transform: rotateZ(360deg);
}
}
/* 旋转的类名 */
.autoRotate {
animation-name: Rotate; /*为 @keyframes 动画规定一个名称*/
animation-iteration-count: infinite; /*animation-iteration-count 属性定义动画的播放次数。这里是无限次播放*/
animation-play-state: paused; /*animation-play-state 属性规定动画正在运行还是暂停。*/
animation-timing-function: linear; /*规定动画的速度曲线。速度曲线定义动画从一套 CSS 样式变为另一套所用的时间。速度曲线用于使变化更为平滑。*/
animation-duration: 5s; /*animation-duration 属性定义动画完成一个周期所需要的时间,以秒或毫秒计。*/
}
.player_con.playing .disc,.player_con.playing .cover {
animation-play-state: running; /* /*animation-play-state 属性规定动画正在运行还是暂停。*/
}
.play_bar {
position: absolute;
left: 200px;
top: -10px;
z-index: 10;
transform: rotate(-25deg); /* 播放杆 转到播放位置 */
transform-origin: 12px 12px; /*transform-origin 属性允许您改变被转换元素的位置。*/
transition: 1s; /* transition是四个transition子项的缩写*/
}
/* 播放杆 转回去 */
.player_con.playing .play_bar {
transform: rotate(0);
}
/*左右分割线样式*/
.switch_btn {
position: absolute;
right: 0;
top: 0;
cursor: pointer;
}
.right_line {
position: absolute;
left: 0;
top: 0;
}
/* 播放进度条部分样式 */
.audio_con{
height: 50px;
background-color: #f1f3f4;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.myaudio{
width: 800px;
height: 40px;
margin-top: 5px;
outline: none; /*outline (轮廓)是绘制于元素周围的一条线,位于边框边缘的外围,可起到突出元素的作用。*/
background-color: #f1f3f4;
}
/* mv播放部分样式 */
.video_con video {
position: fixed;
width: 800px;
height: 546px;
left: 50%;
top: 50%;
margin-top: -273px;
transform: translateX(-50%); /*向X轴逆向平移50%*/
z-index: 990;
}
.mask {
position: fixed;
width: 100%;
height: 600px;
left: 0;
top: 0;
z-index: 980;
background-color: rgba(0, 0, 0, 0.8);
}
三、vue代码实现
接口设计:
1.歌曲搜索接口
请求地址:https://autumnfish.cn/search
请求方法:get
请求参数:keywords(查询关键字)
响应内容:歌曲搜索结果
2.歌曲url获取接口
请求地址:https://autumnfish.cn/song/url
请求方法:get
请求参数:id(歌曲id)
响应内容:歌曲url地址
3.歌曲详情获取
请求地址:https://autumnfish.cn/song/detail
请求方法:get
请求参数:ids(歌曲id)
响应内容:歌曲详情(包括封面信息)
4.热门评论获取
请求地址:https://autumnfish.cn/comment/hot?type=0
请求方法:get
请求参数:id(歌曲id,地址中的type固定为0)
响应内容:歌曲的热门评论
5.mv地址获取
请求地址:https://autumnfish.cn/mv/url
请求方法:get
请求参数:id(mvid,为0表示没有mv)
响应内容:mv的地址
js代码:
var app=new Vue({
el:"#player",
data:{
query:"", //存储搜索框中搜索数据
musicList:[], //保存歌曲信息数组
musicurl:"", //获取歌曲的url
musiccover:"", //歌曲的封面
musichotcomments:[], //歌曲热评数据
isplaying:false, //黑胶碟片动画播放状态,false为不播放
ismv:false, //遮罩层的显示状态,默认false不显示
mvurl:"", //mv播放地址
},
methods: {
searchMusic:function(){ //获取歌曲列表
var that=this;
axios.get("https://autumnfish.cn/search?keywords="+this.query)
.then(function(response){
//console.log(this.query); //打印query参数,看是否双向绑定成功
//console.log(response); //打印response,看打印出来的数据的层级关系
//console.log(response.data.result.songs) //打印此部分看层级关系是否正确,是否取到应该获取到的数据
that.musicList=response.data.result.songs; //使用musicList来保存取到的歌曲列表
},
function(err){
console.log(err);
})
},
musicPlayer:function(id){ //获取歌曲的url
var that=this;
axios.get("https://autumnfish.cn/song/url?id="+id)
.then(function(response){
// console.log(response);
that.musicurl=response.data.data[0].url;
},
function(err){
})
},
musicCover:function(id){ //获取歌曲的封面
var that=this;
axios.get("https://autumnfish.cn/song/detail?ids="+id)
.then(function(response){
//console.log(response); //打印response,看打印出来的数据的层级关系
//console.log(response.data.songs[0].al.picUrl); //打印封面地址
that.musiccover=response.data.songs[0].al.picUrl; //赋值
},
function(err){
})
},
musicComments:function(id){ //获取热评数据
var that=this;
axios.get("https://autumnfish.cn/comment/hot?type=0&id="+id)
.then(function(response){
console.log(response);
that.musichotcomments=response.data.hotComments;
},
function(err){
})
},
play:function(){ //播放状态播放动画
this.isplaying=true;
},
puase:function(){ //暂停状态停止动画
this.isplaying=false;
},
musicmv:function(mvid){ //mv播放
var that=this;
axios.get("https://autumnfish.cn/mv/url?id="+mvid)
.then(function(response){
console.log(response); //打印获取的mv信息
that.mvurl=response.data.data.url; //获取到的mv地址
that.ismv=true;
},
function(err){
})
},
hide:function(){ //隐藏mv播放器
this.puase();
this.ismv=false;
}
}
})
更多推荐
所有评论(0)