1.很多时候要找到完整的API接口很难,但网易云音乐的数据API是可以得到完整的。

安装API:https://github.com/Binaryify/NeteaseCloudMusicApi,只需按照步骤部署就可以的。

提示:由于本地电脑环境千差万别,建议会使用virtualBox虚拟机进行部署可一劳永逸

部署完成,   cd NeteaseCloudMusicApi node app.js   开启服务即可

2.根据相关API开发页面

获取推荐歌单列表

tabBar,主页面色,以及路由设计

{
"pages": [
"pages/home/home",
"pages/hot/hot",
"pages/search/search",
"pages/listdetail/listdetail",
"pages/musicplay/musicplay" ],
"window": {
"backgroundColor": "#F6F6F6",
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#d43c33",
"navigationBarTitleText": "网易云音乐",
"navigationBarTextStyle": "white"
},
"tabBar": {
"backgroundColor": "#212121",
"color": "#8F8F8F",
"selectedColor": "#FFF",
"list": [{
"pagePath": "pages/home/home",
"text": "推荐音乐",
"iconPath": "/images/cm2_btm_icn_discovery.png",
"selectedIconPath": "/images/cm2_btm_icn_discovery_prs.png" },
{
"pagePath": "pages/hot/hot",
"text": "热歌榜",
"iconPath": "/images/cm2_btm_icn_radio.png",
"selectedIconPath": "/images/cm2_btm_icn_radio_prs.png"
},
{
"pagePath": "pages/search/search",
"text": "搜索",
"iconPath": "/images/cm2_btm_icn_music.png",
"selectedIconPath": "/images/cm2_btm_icn_music_prs.png"
}
]
},
"requiredBackgroundModes": ["audio", "location"],
"sitemapLocation": "sitemap.json"
}

tabBar,主页面色,以及路由设计

 "requiredBackgroundModes": ["audio", "location"],

若需要在小程序切后台后继续播放音频,需要在 app.json 中配置 requiredBackgroundModes 属性。

获取API数据,此时有两种方法,使用小程序云函数,或者本地获取

本地获取:
封装request请求get,post

const baseurl = 'http://localhost:3000'
function getbaseurl() {
return baseurl;
}
//get请求
function get(url, data) {
return new Promise((reslove, reject) => {
wx.request({
method: 'GET',
url: baseurl + url,
data,
success: reslove,
fail: reject
})
})
} //post请求
function post(url, data) {
return new Promise((reslove, reject) => {
wx.request({
method: 'POST',
url: baseurl + url,
data,
success: reslove,
fail: reject
})
})
} //需要导出
module.exports = {
get,
post,
getbaseurl
}

request.js

// pages/home/home.js
var requestUrl = require('../../utils/request.js')
Page({ /**
* 页面的初始数据
*/
data: {
musicList: [ ],
detailUrl:''
}, /**
* 生命周期函数--监听页面加载
*/
onLoad: async function (options) {
const res = await requestUrl.get('/personalized/?limit=6')
this.setData({ musicList: res.data.result});
console.log(res.data.result)
},

获取歌单列表

自定义组件还可以自己触发双向绑定更新,做法就是:使用 setData 设置自身的属性

<wxs module="common" src="../../utils/utils.wxs"></wxs>
<view class="m-homeremd">
<h2 class="remd_tl"> 推荐歌单</h2>
<view class="remd_ul">
<navigator url="../listdetail/listdetail?id={{item.id}}" class="remd_li" data-musicid="{{item.id}}" wx:for="{{musicList}}" wx:key="index">
<view class="remd_img">
<image class="u-img" src="{{item.picUrl}}"></image>
<span class="u-earp remd_lnum">{{common.numberFormat(item.playCount)}}</span>
</view>
<text class="remd_text">{{item.name}}</text>
</navigator>
</view>
</view>

渲染歌单页面

推荐歌单页面有一个播放量转换

{{common.numberFormat(item.playCount)}}

function numberFormat(value) {
var param = {};
var k = 10000,
sizes = ['', '万', '亿', '万亿'],
i;
if (value < k) {
param.value = value
param.unit = ''
} else {
i = Math.floor(Math.log(value) / Math.log(k)); param.value = ((value / Math.pow(k, i))).toFixed(2);
param.unit = sizes[i];
}
return param.value + param.unit;
}
module.exports = {
numberFormat: numberFormat
}

utils.wxs

.m-homeremd {
padding-top: 20px;
}
.m-homeremd .remd_tl {
position: relative;
padding-left: 9px;
margin-bottom: 14px;
font-size: 17px;
height: 20px;
line-height: 20px;
}
.m-homeremd .remd_tl:after {
content: " ";
position: absolute;
left: 0;
top: 50%;
margin-top: -9px;
width: 2px;
height: 16px;
background-color: #d33a31;
} .m-homeremd .remd_ul{
display: flex;
flex-wrap: wrap;
}
.m-homeremd .remd_li{
box-sizing: border-box;
flex: 0 1 33.3%;
padding-bottom: 20px;
}
.m-homeremd .remd_img>.u-img{
width: 100px;
height: 100px;
}
.m-homeremd .remd_text {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
padding: 6px 2px 0 6px;
min-height: 30px;
line-height: 1.2;
font-size: 13px;
}
.m-homeremd .remd_img {
position: relative;
}
.m-homeremd .remd_lnum {
position: absolute;
right: 5px;
top: 2px;
z-index: 3;
padding-left: 13px;
color: #fff;
font-size: 12px;
background-position: 0;
background-repeat: no-repeat;
background-size: 11px 10px;
text-shadow: 1px 0 0 rgba(0,0,0,.15);
}
.u-earp {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAQAAABKfvVzAAABfUlEQVR4AZXSA0y/YRAH8PvbdhqyrbnmMDPXFIYwZmt2bo5jDRlDtu1mZHc9z737/Z7t4n833ffu8+p5Af+zePAZQ7AaB3AF57Ebq0X35X7wBhNxEXdZLWKSmNwB/mATW1XVjH84+IdD2nC/tyclLuC9u5l3QmBXyn6vlorpPwXkw7TK+HqjJ+WVG7iqeuXWlXK9QaQV3ygQQ+ubFVFiyRp+gRjBc3gLP0XnWh11vUkkRgc+45wMetPBBX7xzyiQS28agTmxSSBYtof9X9zg051f/vMXt8N+IqEErqpl05/Dr64KfvVnyx2xKcHFsGyKA+DZveBZob/cuRgigNui2YE/D/4Qf2hrm4D2peHdg+CdtoUKoC+OifLhq/pcgWt6JBylYIADfa4eabH0amW5jGJRHOjypfKrlaUyAuAif4LHgParaMAYnMHkMUBbxgh8wAHPFTin/+l0ggOWK9AYdzZzPl8bwwDPFQBHei17DlTOwVdwEMMvHPAc8D/rBs0Gmx5Y/w/0AAAAAElFTkSuQmCC');
}

css样式

列表页面渲染:根据id值跳转到相对应的列表页面

<navigator url="../listdetail/listdetail?id={{item.id}}" class="remd_li"  data-musicid="{{item.id}}" wx:for="{{musicList}}" wx:key="index">

import {get} from "../../utils/request.js"
// pages/listdetail/listdetail.js
Page({ /**
* 页面的初始数据
*/
data: {
detailList:[ ]
}, /**
* 生命周期函数--监听页面加载
*/
onLoad: async function (options) {
console.log(options)
const url =`/playlist/detail?id=${options.id}`
const res = await get(url)
console.log(res.data)
this.setData({ detailList: res.data.playlist}) },

listdetail.js

<!-- <wxs module="common" src="../../utils/utils.wxs"></wxs>
<view class="u-plhead pylst_header">
<view class="plhead_bg" style="background-image:url({{detailList.playlist.coverImgUrl}})">
</view>
<view class="plhead_wrap">
<view class="plhead_fl lsthd_fl">
<image src="{{detailList.playlist.coverImgUrl}}" class='u-img'>{{detailList.playlist.coverImgUrl}}</image>
<span class="lsthd_icon">歌单</span>
<i class="u-earp lsthd_num">{{common.numberFormat(detailList.playlist.playCount)}}</i>
</view>
<view class="plhead_fr">
<h2 class="f-thide2 f-brk lsthd_title">{{detailList.playlist.name}}</h2>
<view class="lsthd_auth f-thide">
<a class="lsthd_link" href="">
<view class="u-avatar lsthd_ava">
<image class="u-img" src="{{detailList.playlist.creator.avatarUrl}}"></image>
<span class="ava-icon ava-icon-daren"></span> </view>
{{detailList.playlist.creator.nickname}}
</a>
</view>
</view>
</view>
</view>
<h3 class="u-smtitle">歌曲列表</h3>
<view class="m-sglst"wx:for="{{detailList}}" wx:key="index">
<view class="m-list"wx:for="{{item.tracks}}" wx:for-item="item" wx:key="index">
<navigator class="m-sgitem"url="/">
<view class="sgfl">{{index+1}}</view>
<view class="sgfr f-bd f-bd-btm">
<view class="sgchfl">
<view class="f-thide sgtl">{{item.name}}</view>
<view class="f-thide sginfo">{{}}</view>
</view>
<view class="sgchfr">
<span class="u-hmsprt sgchply">
</span>
</view>
</view>
</navigator>
</view>
</view> -->
<wxs module="common" src="../../utils/utils.wxs"></wxs>
<view class="u-plhead pylst_header">
<view class="plhead_bg" style="background-image:url({{detailList.coverImgUrl}})">
</view>
<view class="plhead_wrap">
<view class="plhead_fl lsthd_fl">
<image w-if="detailList.coverImgUrl" src="{{detailList.coverImgUrl}}" class='u-img'></image>
<span class="lsthd_icon">歌单</span>
<i class="u-earp lsthd_num">{{common.numberFormat(detailList.playCount)}}</i>
</view>
<view class="plhead_fr">
<h2 class="f-thide2 f-brk lsthd_title">{{detailList.name}}</h2>
<view class="lsthd_auth f-thide">
<a class="lsthd_link" href="">
<view class="u-avatar lsthd_ava">
<image class="u-img" src="{{detailList.creator.avatarUrl}}"></image>
<span class="ava-icon ava-icon-daren"></span> </view>
{{detailList.creator.nickname}}
</a>
</view>
</view>
</view>
</view>
<h3 class="u-smtitle">歌曲列表</h3>
<view class="m-sglst"wx:for="{{detailList.tracks}}" wx:key="index">
<!-- <view class="m-list"wx:for="{{item.tracks}}" wx:for-item="item" wx:key="index"> -->
<navigator class="m-sgitem"url="../musicplay/musicplay?id={{item.id}}&title={{item.name}}">
<view class="sgfl">{{index+1}}</view>
<view class="sgfr f-bd f-bd-btm">
<view class="sgchfl">
<view class="f-thide sgtl">{{item.name}}
<span class="sgalia" wx:if="{{item.alia.length}}">(<!-- -->{{item.alia}}<!-- -->)</span>
</view>
<view class="f-thide sginfo">{{item.ar[0].name}}-{{item.al.name}}</view>
</view>
<view class="sgchfr">
<span class="u-hmsprt sgchply">
</span>
</view>
</view>
</navigator>
<!-- </view> -->
</view>

listdetail页面渲染

.plhead_wrap {
display: flex;
position: relative;
z-index: 2;
}
.u-plhead {
position: relative;
padding: 30px 10px 30px 15px;
overflow: hidden;
}
.u-plhead .plhead_bg {
background-repeat: no-repeat;
background-size: cover;
background-position: 50%;
-webkit-filter: blur(20px);
filter: blur(20px);
-webkit-transform: scale(1.5);
-ms-transform: scale(1.5);
transform: scale(1.5);
}
.u-plhead .plhead_bg, .u-plhead .plhead_bg:after {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
z-index: 1;
}
.u-plhead .plhead_bg:after {
content: " ";
background-color: rgba(0,0,0,.25);
}
.pylst_header .lsthd_title {
padding-top: 1px;
font-size: 17px;
line-height: 1.3;
color: #fefefe;
height: 44px;
display: -webkit-box;
-webkit-box-pack: center;
}
.plhead_fl {
position: relative;
width: 114px;
height: 114px;
background-color: #e2e2e3;
}
image.u-img {
width: 100%;
height: 100%;
}
.pylst_header .lsthd_icon {
position: absolute;
z-index: 3;
top: 10px;
left: 0;
padding: 0 8px;
height: 17px;
color: #fff;
font-size: 9px;
text-align: center;
line-height: 17px;
background-color: rgba(217,48,48,.8);
border-top-right-radius: 17px;
border-bottom-right-radius: 17px;
}
.u-plhead .plhead_fr {
-webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
width: 1%;
margin-left: 16px;
}
.pylst_header .lsthd_ava {
display: inline-block;
width: 30px;
height: 30px;
border-radius: 50%;
vertical-align: middle;
margin-right: 5px;
}
.u-avatar {
position: relative;}
.u-avatar>.u-img {
border-radius: 50%; }
.u-avatar .ava-icon.ava-icon-daren {
background-position: -40px 0;
}
.u-avatar .ava-icon {
position: absolute;
right: -5px;
bottom: 0;
width: 12px;
height: 12px;
background-image: url(//s3.music.126.net/mobile-new/img/usericn_2x.png?6423c06…=);
background-repeat: no-repeat;
background-size: 75px auto;
}
.pylst_header .lsthd_auth {
display: block;
position: relative;
margin-top: 20px;
}
.lsthd_link {
display: inline-block;
color: hsla(0,0%,100%,.7);
}
.f-thide {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
word-break: normal;
}
.pylst_header .lsthd_num {
position: absolute;
right: 2px;
top: 0;
z-index: 3;
padding-left: 15px;
color: #fff;
font-size: 12px;
background-position: 0;
background-repeat: no-repeat;
background-size: 11px 10px;
text-shadow: 1px 0 0 rgba(0,0,0,.15);
}
.lsthd_fl:after {
content: " ";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 18px;
z-index: 2;
background-image: -webkit-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,.2));
background-image: linear-gradient(90deg,rgba(0,0,0,0),rgba(0,0,0,.2));
}
.u-earp {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAQAAABKfvVzAAABfUlEQVR4AZXSA0y/YRAH8PvbdhqyrbnmMDPXFIYwZmt2bo5jDRlDtu1mZHc9z737/Z7t4n833ffu8+p5Af+zePAZQ7AaB3AF57Ebq0X35X7wBhNxEXdZLWKSmNwB/mATW1XVjH84+IdD2nC/tyclLuC9u5l3QmBXyn6vlorpPwXkw7TK+HqjJ+WVG7iqeuXWlXK9QaQV3ygQQ+ubFVFiyRp+gRjBc3gLP0XnWh11vUkkRgc+45wMetPBBX7xzyiQS28agTmxSSBYtof9X9zg051f/vMXt8N+IqEErqpl05/Dr64KfvVnyx2xKcHFsGyKA+DZveBZob/cuRgigNui2YE/D/4Qf2hrm4D2peHdg+CdtoUKoC+OifLhq/pcgWt6JBylYIADfa4eabH0amW5jGJRHOjypfKrlaUyAuAif4LHgParaMAYnMHkMUBbxgh8wAHPFTin/+l0ggOWK9AYdzZzPl8bwwDPFQBHei17DlTOwVdwEMMvHPAc8D/rBs0Gmx5Y/w/0AAAAAElFTkSuQmCC');
}
.m-sgitem, .m-sgitem .sgfl {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.m-sgitem {
padding-left: 10px;
}
.m-sgitem .sgfr {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
position: relative;
}
.m-sgitem .sgfl {
-webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
width: 40px;
font-size: 17px;
color: #999;
margin-left: -10px;
}
.m-sgitem .sgchfl {
padding: 6px 0;
width: 0;
}
.m-sgitem .sgtl {
font-size: 17px;
}
.m-sgitem .sginfo {
font-size: 12px;
color: #888;
}
.m-sgitem .sgchply {
display: inline-block;
width: 22px;
height: 22px;
background-position: -24px 0;
}
.u-hmsprt {
background: url(//s3.music.126.net/mobile-new/img/index_icon_2x.png?5207a28…=) no-repeat;
background-size: 166px 97px;
}
.m-sgitem .sgchfl, .m-sgitem .sgfr {
-webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
}
.m-sgitem .sgchfr {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
-webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
padding: 0 10px;
}
.m-sgitem .sgalia {
color: #888;
margin-left: 4px;
}
.u-smtitle {
height: 23px;
line-height: 23px;
padding: 0 10px;
font-size: 12px;
color: #666;
background-color: #eeeff0;
}

listdetail页面样式

下一章介绍歌曲播放页面(唱片旋转,歌曲进度条,以及歌词滚动等效果)

仿网易云音乐-微信小程序开发的更多相关文章

  1. [干货教程]仿网易云课堂微信小程序开发实战经验

    本篇文章想跟大家分享下:我们公司“湖北诚万兴科技”最近刚帮客户定制开发.目前已上线的“哎咆课堂”微信小程序的开发经验分享.首先大概介绍下这个小程序所涉及到的主要技术点:微信登录.微信支付.微信小程序F ...

  2. [Chat]实战:仿网易云课堂微信小程序开发核心技术剖析和经验分享

    本Chat以一个我参与开发并已上线运营近2年——类似网易云课堂的微信小程序项目,来进行微信小程序高级开发的学习. 本场Chat围绕项目开发核心技术分析,帮助你快速掌握在线视频.音频类小程序开发所需要的 ...

  3. 微信小程序开发日记——高仿知乎日报(下)

    本人对知乎日报是情有独钟,看我的博客和github就知道了,写了几个不同技术类型的知乎日报APP 要做微信小程序首先要对html,css,js有一定的基础,还有对微信小程序的API也要非常熟悉 我将该 ...

  4. 微信小程序开发日记——高仿知乎日报(中)

    本人对知乎日报是情有独钟,看我的博客和github就知道了,写了几个不同技术类型的知乎日报APP要做微信小程序首先要对html,css,js有一定的基础,还有对微信小程序的API也要非常熟悉 我将该教 ...

  5. 微信小程序开发日记——高仿知乎日报(上)

    本人对知乎日报是情有独钟,看我的博客和github就知道了,写了几个不同技术类型的知乎日报APP 要做微信小程序首先要对html,css,js有一定的基础,还有对微信小程序的API也要非常熟悉 我将该 ...

  6. 《云阅》一个仿网易云音乐UI,使用Gank.Io及豆瓣Api开发的开源项目

    CloudReader 一款基于网易云音乐UI,使用GankIo及豆瓣api开发的符合Google Material Desgin阅读类的开源项目.项目采取的是Retrofit + RxJava + ...

  7. 微信小程序开发学习资料

    作者:初雪链接:https://www.zhihu.com/question/50907897/answer/128494332来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...

  8. 微信小程序开发中的二三事之网易云信IMSDK DEMO

    本文由作者邹永胜授权网易云社区发布. 简介 为了更好的展示我们即时通讯SDK强悍的能力,网易云信IM SDK微信小程序DEMO的开发就提上了日程.用产品的话说就是: 云信 IM 小程序 SDK 的能力 ...

  9. 我们的微信小程序开发

    基于微信小程序的系统开发准备工作 腾讯推出微信小程序也有一段时间了,在各种行业里面也都掀起一阵阵的热潮,很多APP应用被简化为小程序的功能迅速推出,同时也根据小程序的特性推出各种独具匠心的应用,相对传 ...

  10. C# WPF 低仿网易云音乐(PC)歌词控件

    原文:C# WPF 低仿网易云音乐(PC)歌词控件 提醒:本篇博客记录了修改的过程,废话比较多,需要项目源码和看演示效果的直接拉到文章最底部~ 网易云音乐获取歌词的api地址 http://music ...

随机推荐

  1. hadoop集群实现分发文件命令xsync脚本文件

    1 #!/bin/bash 2 3 #1. 判断参数个数 4 if [ $# -lt 1 ] 5 then 6 echo Not Enough Arguement! 7 exit; 8 fi 9 10 ...

  2. Android---intent和startActivityForResult方法的使用---页面跳转和数据回传

    Android页面跳转和数据回传 今天我尝试用两个页面实现数据的传递和回传,出现了一些问题,把问题已经成功的案例总结如下: 具体是这样的: 有两个layout布局,两个activity.MainAct ...

  3. Unity最新一键清理Prefab中所有MissingComponent

    因为老的API  Properties.DeleteArrayElementAtIndex(propertyIndex);提示没权限修改, 而unity提供了新的API  GameObjectUtil ...

  4. #单调栈,树状数组#CF1635F Closest Pair

    题目 设 \(f(x,y)=|a_x-a_y|*(w_x+w_y)\),其中 \(a\) 单调递增 多组询问求 \(\min_{l\leq l'<r'\leq r}\{f(l',r')\}\) ...

  5. #期望dp#51nod 2015 诺德街

    题目传送门 分析 禁不住 QuantAsk 的诱惑(bushi) 考虑一条路线可以由若干段 \(1-2-\dots-n-\dots-2\) 以及 最后一段 \(1-\dots-x\) 组成. 对于最后 ...

  6. go~istio加载wasm的步骤

    参考 https://github.com/higress-group/proxy-wasm-go-sdk/tree/main/proxywasm https://github.com/tetrate ...

  7. 战码先锋直播预告丨参与ArkUI,共建OpenHarmony繁荣生态

    OpenAtom OpenHarmony(以下简称"OpenHarmony")工作委员会首度发起「OpenHarmony开源贡献者计划」,旨在鼓励开发者参与OpenHarmony开 ...

  8. openGauss/MogDB数据库安装部署之xlog目录设置

    openGauss/MogDB 数据库安装部署之 xlog 目录设置 本文出处:https://www.modb.pro/db/176915 关于 xlog xlog 文件是一个记录事务日志的文件,它 ...

  9. 第一篇:Python入门基础

    主要内容 1.Python简介 2.变量 3.字符编码 4.用户交互 5.if 流程判断 6.while循环 7.for循环 一.Python简介 1.python的创始人为吉多·范罗苏姆(Guido ...

  10. 基于 Java 编程生成二维码图片

    0x01 准备 (1)软件版本 IntelliJ IDEA 2023.1.3 JDK 18 Tomcat 10.1.11 Maven 3.8.6 (2)技术栈 servlet zxing 谷歌项目 生 ...