最后一个页面还没写完,由于我要去比赛,所以暂时先写到这,等放假了再写
其他页面可以看我页面专栏 Vue3实战项目-网易云APP 。
大家觉得有些地方可以写的更好写法可以给我留言私信,我会去修改
如果文章对你有帮助请点一个赞或收藏,谢谢
1、准备工作
然后我们来实现播放界面也就是下面这张图
这是一个新的页面,我们还是利用路由进行跳转,先创建一个playerUi.vue
然后,我们在router
中设置路由
,{
path: '/PlayerUi',
name: 'PlayerUi',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/PlayerUi.vue')
}
然后我们设置路由跳转,根据手机App上的网易云,我们可以知道,歌单列表左边部分可以跳转到该页面还有下面播放按钮的左边部分
那么我们就在这两个部分设置路由跳转,这两个位置分别在playlistView.vue
和playController.vue
下
然后效果就是下面这样
然后我们开始找资源,找下面两张图片,接口我没有看见有图片。
我们打开网易云音乐的官网,随便点击一首歌,用f12用手机的宽度去打开
https://music.163.com/
然后我们点击network
选择Img
找到这几张图片,双击会跳转到单独的页面右键保存即可
然后给它拖到assets
文件夹中的img
文件夹下面就好了,然后我们来看看接口文档,我们需要的是歌曲的详情和歌词
然后我们在api
这个文件夹的index.js
下封装一下,
// 获取歌曲详细
function postSongDetail(id){
return axios.post(`${baseUrl}/song/detail?ids=${id}`)
}
// 获取歌词
function postLyric(id){
return axios.post(`${baseUrl}/lyric?id=${id}`)
}
然后我们在到 PlayerUi.vue
中测试一下
<script>
import palyerUiTop from '@/components/playerUi/palyerUiTop.vue'
import { onMounted,reactive } from 'vue';
import {useRoute} from 'vue-router'
import {postLyric,postSongDetail} from '@/api/index';
export default {
components:{
palyerUiTop
},
setup(){
const route = useRoute()
let stateLyric = reactive({})
let stateSongDetail = reactive({})
onMounted(async()=>{
// 接收传过来的歌曲ID
let id = route.query.id
// 请求
let Lyric = await postLyric(id)
let SongDetail = await postSongDetail(id)
// 接收数据
stateLyric = Lyric.data
stateSongDetail = SongDetail.data
console.log(Lyric.data);
console.log(stateSongDetail);
})
}
}
</script>
这样就算好了,然后数据我们等会在处理,先把框架搭好 ,然后我们在components
下创建一个文件夹,取名叫playerUi
,新建一个子组件 playerUiTop.vue
开始写顶部
2、顶部布局
接下来我们实现顶部的布局
先把图标引用进来,这里的歌名和作者,我们临时给它定一个,先调整样式,在接收数据进行处理。
<template>
<div class="playUiTop">
<!-- 左边返回键 -->
<div class="left">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-xiangxiajiantou"></use>
</svg>
</div>
<!-- 中间歌名和作者名 -->
<div class="middle">
<div class="title">title</div>
<div class="name">777</div>
</div>
<!-- 右边分享 -->
<div class="right">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-fenxiang"></use>
</svg>
</div>
</div>
</template>
然后我们来调整样式,同样利用flex布局使它平均分布,然后给上边距。
.playUiTop{
display: flex;
justify-content: space-between;
padding-top: 10px;
}
这里的左右边距,我是在playerUi.vue
中给的
.palyerUi{
width: 7.5rem;
padding: 0 0.4rem;
}
接下来调整图标大小就可以了,然后给上一个白色的效果
.icon{
width: 0.5rem;
height: 0.5rem;
fill: #fff;
}
由于背景是白色的,所以有点看不清楚,等会我们接收数据渲染背景就好了。然后调整中间的字体,这里少了一个 >
的图标,我们给它加上
<div class="name">
777
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-gengduo1"></use>
</svg>
</div>
然后,我们看到这个图标也是受到影响的,我们也给它调整一下,顺便调整一下字体
.middle{
color: #fff;
align-items: center;
.title{
font-size: 20px;
}
.name{
opacity: 0.5;
}
.icon{
width: 0.24rem;
height: 0.24rem;
}
}
然后整体居中一下
align-items:Center;
然后,我们把数据传过来,渲染一下标题,背景的话我打算直接在PlayerUi.vue
中渲染,这里修改一下接收参数
它这里是这样的,我们也改成这样样子
let stateSongDetail = reactive({
songs:{
}
})
stateSongDetail.songs = SongDetail.data.songs[0]
然后把数据传给playerUiTop.vue
<palyerUiTop :songs = "stateSongDetail.songs"></palyerUiTop>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fBPs1rY8-1656895020777)
然后我们先做一下背景,不然看不出效果
很显然这个背景又是加了滤镜的,我们只需要把这个图片请求下来然后加滤镜就好了,我们首先加个img
<img class="bg" :src="stateSongDetail.songs.al.picUrl" alt="">
z’za
这个样式,我们在歌单列表用过,所以直接拷过来就行
.bg{
position:fixed;
left:0;
top: 0;
width: 7.5rem;
z-index: -1;
filter: blur(100px);
overflow: hidden;
transform: scale(4);
}
效果就是这样,然后我们回到playerUiTop.vue
中,把歌名和作者渲染一下,这里接收一下数据
props:['songs'],
<!-- 中间歌名和作者名 -->
<div class="middle">
<div class="title">{{songs.name}}</div>
<!-- 作者名 -->
<div class="name">
<span v-for="(itemName,j) in songs.ar" :key = "j">
<span v-if="j==songs.ar.length-1">{{itemName.name}}</span>
<span v-else>{{itemName.name}}/</span>
</span>
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-gengduo1"></use>
</svg>
</div>
</div>
这里的字体没有居中,然后应该你们的字体会大一点,我这里给它调小了,然后我们来修改一下字体
.title{
font-size: 15px;
text-align: center;
}
.name{
opacity: 0.5;
text-align: center;
}
效果就出来了。然后这里的文字还有个走马灯效果,我这里就偷个懒借用vant3
中的NoticeBar 通知栏
,vant
不会引用的看官方文档或者我的Vue3+node.js网易云音乐实战项目(三)
这篇中的轮播图实现,这里我采用下面这种方式
然后咱稍微修改一下代码
<van-notice-bar :text= "songs.name" color="#fff" background="transparent" />
.van-notice-bar{
font-size: 15px;
width: 3rem;
}
效果
然后这里需要给个宽度,让它不超出款的时候不动
.van-notice-bar{
font-size: 15px;
width: 4rem;
/deep/
.van-notice-bar__wrap{
.van-notice-bar__content{
padding-left: 35px;
}
}
然后这里要给个/deep/
不然设置不了,然后居中属性我一直没调好,就只能给个内边距,这里有其他方法可以给我留个言
最后给加个返回事件
<div class="left" @click="$router.back()" >
</div>
3、中部唱片部分布局
我们开始做唱片部分,也就是下面这个部分,
之前准备工作那里,我们已经下载好了放在了assets
的img
下面,现在我们把它引用进来,先创建好一个子组件palerUiDisc.vue
组件,然后在PlayerUI.vue
中引用
<template>
<div class="playerUiDisc">
<div class="img">
<img class="needle" src="@/assets/img/needle-ab.png" alt="">
<img class="circle" src="@/assets/img/circle.png" alt="">
<img class="playImg" :src="songs.al.picUrl" alt="">
</div>
<div class="bottonIcon">
</div>
</template>
然后我们来调整大小和宽度,这里利用定位去做
.img{
position: absolute;
width: 7.5rem;
height: 7.5rem;
left: 0;
top: 1.5rem;
.needle{
width: 2.5rem;
height: auto;
position: absolute;
left: 3.3rem;
// 旋转
transform-origin: 0.3rem 0;
//旋转多少
transform: rotate(-20deg);
z-index: 10;
}
.circle{
width: 5.5rem;
height: auto;
position: absolute;
left:calc(50% - 2.75rem) ;
top: 2.5rem;
}
}
然后这样摆臂是个活动的,那我们在给它加一个active
状态,这里我们可以用浏览器去先调整一下样式,看看要到多少合适
很显然到3的时候,效果最好,那我我们就摆动到3
.needle.active{
width: 2.5rem;
height: auto;
position: absolute;
left: 3.3rem;
// 旋转多少度
transform-origin: 0.3rem 0;
transform: rotate(3deg);
z-index: 10;
}
然后我们来给个图片试试效果,这里先从PlayerUi.vue
传数据过来
这边接收一下
//template
<img class="playImg" :src="songs.al.picUrl" alt="">
//script
props:['songs']
调整一下大小和位置
.playImg{
width: 3.4rem;
height: 3.4rem;
border-radius: 100%;
position: absolute;
left:calc(50% - 1.7rem) ;
top: 3.55rem;
}
接下来实现这个部分
找好图标把图标放进去
<div class="bottonIcon">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-xihuan"></use>
</svg>
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-xiazai"></use>
</svg>
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-changpian"></use>
</svg>
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-pinglun-"></use>
</svg>
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-gengduo-shuxiang"></use>
</svg>
</div>
调整一下边距和位置还有大小
.bottonIcon{
width: 7.5rem;
display: flex;
justify-content: space-evenly;
position: absolute;
bottom: 3rem;
left:calc(50% - 3.7rem) ;
.icon{
width: 0.5rem;
height: 0.5rem;
fill: #fff;
}
}
然后这里还有个问题,如果有些时候没有请求到图片,我们需要把唱片改成红色的底片。我们利用v-if
来进行判断
<img class="playImg" v-if="songs.al.picUrl" :src="songs.al.picUrl" alt="">
<img class="playImg" v-else="songs.al.picUrl" src="@/assets/img/disc.png" alt="">
然后大的背景也是一样的,我们也做一下修改
<img class="bg" v-if="stateSongDetail.songs.al.picUrl" :src="stateSongDetail.songs.al.picUrl" alt="">
<img class="bg" v-else="stateSongDetail.songs.al.picUrl" src="@/assets/img/disc.png" alt="">
4、底部部分布局
接下来,我们来实现底部部分的布局
先把大的框架搭好
<template>
<div class="playUiButton">
<div class="top">
</div>
<div class="button">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-xihuan"></use>
</svg>
</div>
</div>
</template>
首先是上面的一部分,一个进度条,我们还是采用vant
的进度条来弄
先把它插入进来,设置一下颜色和字,具体参数可以看vant
<div class="top">
<van-progress :percentage="5" pivot-text=" " color="#fff" stroke-width="1px" />
</div>
然后给它变成圆角,设置一下长度
.top{
/deep/
.van-progress{
color:#fff;
width: 6rem;
.van-progress__pivot{
font-size: 1px;
width: 0.2rem;
height: 0.2rem;
border-radius: 100%;
}
}
}
然后我们利用定位调整一下位置
.top{
display: flex;
position: absolute;
left: 0;
bottom: 2rem;
/deep/
.van-progress{
color:#fff;
width: 5rem;
position: absolute;
left:58px ;
.van-progress__pivot{
font-size: 1px;
width: 0.2rem;
height: 0.2rem;
border-radius: 100%;
}
}
}
左右两边价格时间戳,先占个位置。
<p class="p1">00:00</p>
<van-progress :percentage="5" pivot-text=" " color="#fff" stroke-width="1px" />
<p class="p2">00:00</p>
.p1{
position: absolute;
left: 0.1rem;
top: -10px;
}
.p2{
position: absolute;
left: 6.4rem;
top: -10px;
}
然后接下来调整下面这部分的按钮,在这个之前我们先把播放组件取消显示