摘要:初窺添加音樂(lè)到收藏最近列表歌詞滾動(dòng)從一個(gè)開(kāi)始微信開(kāi)發(fā)者工具生成目錄如下主頁(yè)日志頁(yè)面工具大體為每一個(gè)即是一個(gè)頁(yè)面文件,每個(gè)頁(yè)面有一個(gè)文件規(guī)定描述頁(yè)面的這四個(gè)文件必須具有相同的路徑與文件名。
todo:
[ ] 添加音樂(lè)到收藏(最近)列表
[ ] 歌詞滾動(dòng)
從一個(gè)hello world開(kāi)始微信開(kāi)發(fā)者工具生成 目錄如下:
. |-- app.js |-- app.json |-- app.wxss |-- pages | |-- index # 主頁(yè) | | |-- index.js | | |-- index.json | | |-- index.wxml | | `-- index.wxss | `-- log # 日志頁(yè)面 | | |-- log.js | | |-- log.json | | |-- log.wxml | | `-- log.wxss `-- utils # 工具 `-- util.js
大體為:
每一個(gè)page即是一個(gè)頁(yè)面文件 ,每個(gè)頁(yè)面有一個(gè)js/wxml/wxss/json文件 規(guī)定:描述頁(yè)面的這四個(gè)文件必須具有相同的路徑與文件名。
全局下同路,為公共的邏輯,樣式,配置
與html不同:用view text navigator 代替 div span a
app.json: 注冊(cè)pages window tabBar networkTimeout
組件說(shuō)明
*.js: 作為邏輯層 與wxml交互 有著豐富的
網(wǎng)絡(luò),
媒體,
文件,
數(shù)據(jù)緩存,
位置,
設(shè)備,
界面...的api
官方文檔
*.wxml: 數(shù)據(jù)驅(qū)動(dòng)的視圖層 + 微信提供了大量的組件 表單 導(dǎo)航 媒體 ...
weui為小程序提供了 weui.wxcss 但大多是造官方組件的輪子
這里精選,也算是補(bǔ)充兩個(gè)常用組件
對(duì)于小程序沒(méi)有DOM操作 不熟悉mvvm思想的同學(xué) 是個(gè)很好的入門(mén)
navbar
{{item}} 選項(xiàng)一的內(nèi)容 選項(xiàng)二的內(nèi)容 選項(xiàng)三的內(nèi)容
block渲染data里面的四個(gè)tabs,slider為激活tab選項(xiàng)時(shí)候的表現(xiàn),panel為內(nèi)容面板
//js var sliderWidth = 96; // 需要設(shè)置slider的寬度,用于計(jì)算中間位置 Page({ data: { tabs: ["選項(xiàng)一", "選項(xiàng)二", "選項(xiàng)三"], activeIndex: 1, sliderOffset: 0, sliderLeft: 0 }, onLoad: function () { var that = this; wx.getSystemInfo({ success: function(res) { that.setData({ sliderLeft: (res.windowWidth / that.data.tabs.length - sliderWidth) / 2, sliderOffset: res.windowWidth / that.data.tabs.length * that.data.activeIndex }); } }); }, tabClick: function (e) { this.setData({ sliderOffset: e.currentTarget.offsetLeft, activeIndex: e.currentTarget.id }); } });
了解mvvm思想的同學(xué)不難看出 通過(guò)tabs數(shù)組渲染出來(lái)選項(xiàng)后每次點(diǎn)擊獲取id 然后通過(guò)設(shè)置hidden顯示或隱藏
searchbar
取消 實(shí)時(shí)搜索文本
一個(gè)input輸入框+一個(gè)搜索label+一個(gè)清楚內(nèi)容的icon + 取消按鈕
Page({ data: { inputShowed: false, inputVal: "" }, showInput: function () { this.setData({ inputShowed: true }); }, hideInput: function () { this.setData({ inputVal: "", inputShowed: false }); }, clearInput: function () { this.setData({ inputVal: "" }); }, inputTyping: function (e) { this.setData({ inputVal: e.detail.value }); } });
input上面有一層label 通過(guò)Page里面狀態(tài)的改變而操作其wxml狀態(tài)的改變
不難體會(huì)到:小程序和Vue的思想還是挺接近的
---獲取云音樂(lè)api
巨人的源github項(xiàng)目
在此我將他部署到leancloud上
即可在線訪問(wèn),免去煩人的本地localhost啟動(dòng),在線url
http://neteasemusic.leanapp.cn
調(diào)用例子:
http://neteasemusic.leanapp.c...海闊天空
http://neteasemusic.leanapp.c...
具體參考api
一切具備 只欠東風(fēng)詳細(xì)文檔
生成目錄
本文講解核心內(nèi)容音樂(lè)的播放,讀者可自己實(shí)現(xiàn)其余頁(yè)面。
. |-- app.js |-- app.json |-- app.wxss |-- common.js #公用js |-- images #存放項(xiàng)目圖片 |-- style | ? |-- weui.wxss ? # 引入weui樣式 ?萬(wàn)一你自己不想寫(xiě)css樣式呢 |-- pages | ? |-- find ? # 發(fā)現(xiàn)音樂(lè) | ? | ? |-- index.js | | |-- index.json | | |-- index.wxml | | `-- index.wxss | ? |--my ? # 我的音樂(lè) | ? | ? |-- index.js | | |-- index.json | | |-- index.wxml | | `-- index.wxss | ? |--now? # 正在播放 | ? | ? |-- index.js | | |-- index.json | | |-- index.wxml | | `-- index.wxss | ? |--account ? # 賬號(hào) | ? | ? |-- index.js | | |-- index.json | | |-- index.wxml | | `-- index.wxss | |-- index # 主頁(yè) | | |-- index.js | | |-- index.json | | |-- index.wxml | | `-- index.wxss | `-- log # 日志頁(yè)面 `-- utils # 工具 `-- util.js
請(qǐng)先在在app.json中注冊(cè)頁(yè)面,設(shè)置navigation,配置tabbar
{ "pages":[ "pages/find/index", "pages/my/index", "pages/now/index", "pages/account/index", "pages/index/index" ], "window":{ "backgroundTextStyle":"light", "navigationBarBackgroundColor": "#D43C33", "navigationBarTitleText": "網(wǎng)易云音樂(lè)", "navigationBarTextStyle":"white", "backgroundColor": "#FBFCFD" }, "tabBar": { "backgroundColor":"#2A2C2E", "color": "#a7a7a7", "selectedColor": "#ffffff", "list": [{ "iconPath":"./images/find.png", "selectedIconPath":"./images/find1.png", "pagePath":"pages/find/index", "text": "發(fā)現(xiàn)音樂(lè)" }, { "iconPath":"./images/my.png", "selectedIconPath":"./images/my1.png", "pagePath": "pages/my/index", "text": "我的音樂(lè)" }, { "iconPath":"./images/now.png", "selectedIconPath":"./images/now1.png", "pagePath": "pages/now/index", "text": "正在播放" }, { "iconPath":"./images/account.png", "selectedIconPath":"./images/account1.png", "pagePath": "pages/account/index", "text": "賬號(hào)" }] } }
發(fā)現(xiàn)音樂(lè)
布局分為搜索框,navbar,swiper滑動(dòng),三列,以及兩行三列構(gòu)成
tips:小程序中flex布局基本無(wú)兼容性問(wèn)題 ,可大膽使用
前三個(gè)可用上文提到的組件和小程序swiper組件快速完成,
對(duì)于搜索功能
我們?cè)谒阉鱥nput上綁定一個(gè)inputTyping事件,這樣每次鍵入完畢都可以得到結(jié)果,然后我們直接請(qǐng)求api
//index.js //獲取應(yīng)用實(shí)例 // 個(gè)人網(wǎng)易云音樂(lè) ID 66919655 var app = getApp() Page({ data: { searchReault: [] }, ? ?//綁定事件 ? ?inputTyping: function (e) { let that = this console.log(e.detail) this.setData({ inputVal: e.detail.value }); wx.request({ url: "http://neteasemusic.leanapp.cn/search", data: { keywords: e.detail.value }, method: "GET", success: function (res) { let temp = [] if(!res.data.result.songs){ return ; } ? ? ? ? ? ? ? ?//遍歷數(shù)據(jù) ? ? ? ? ? ? ? ?res.data.result.songs.forEach((song, index) => { temp.push({ id: song.id, name: song.name, mp3Url: song.mp3Url, picUrl: song.album.picUrl, singer: song.artists[0].name }) ? ? ? ? ? ? ? ? ? ?//設(shè)置數(shù)據(jù) ? ? ? ? ? ? ? ? ? that.setData({ searchReault: temp }) }) // 存入搜索的結(jié)果進(jìn)緩存 wx.setStorage({ key:"searchReault", data:temp }) } }) } });
data里面的searchReault數(shù)組存入搜索結(jié)果,發(fā)起一個(gè)wx.request,用GET方式傳入?yún)?shù),組織好json后設(shè)置data,然后將搜索結(jié)果存入本地緩存
wxml渲染searchReault:
并且自定義data屬性,navigator的打開(kāi)方式為tab切換open-type="switchTab" ,綁定一個(gè)tonow事件bindtap="tonow"
{{item.name}} {{item.singer}}
在tonow事件中,獲取當(dāng)前的歌曲
tonow: function (event) { let songData = { id: event.currentTarget.dataset.id, name: event.currentTarget.dataset.name, mp3Url: event.currentTarget.dataset.songurl, picUrl: event.currentTarget.dataset.picurl, singer: event.currentTarget.dataset.singer } // 將當(dāng)前點(diǎn)擊的歌曲保存在緩存中 wx.setStorageSync("clickdata", songData) wx.switchTab({ url: "../now/index" }) }
正在播放
布局:歌曲封面,滑動(dòng)條上下為操作按鈕,
封面在采用圓角,rotate,transition既可以
滑動(dòng)快進(jìn):在滑動(dòng)條上綁定事件 slider3change
//滑動(dòng) 歌曲快進(jìn) function sliderToseek(e, cb) { wx.getBackgroundAudioPlayerState({ success: function (res) { var dataUrl = res.dataUrl var duration = res.duration let val = e.detail.value let cal = val * duration / 100 cb && cb(dataUrl, cal); } }) } //分隔 在page中調(diào)用 slider3change: function (e) { sliderToseek(e, function (dataUrl, cal) { wx.playBackgroundAudio({ dataUrl: dataUrl }) wx.seekBackgroundAudio({ position: cal }) }) },
一個(gè)自定義的sliderToseek函數(shù):
參數(shù)e 可以獲取滑動(dòng)的值,獲取正在播放的音樂(lè)信息成功后執(zhí)行回調(diào)函數(shù)1->播放 回調(diào)函數(shù)2->跳到指定位置;
拆分歌詞:
在api中得到的歌詞:"[00:00.00] 作曲 : 黃家駒 [00:01.00] 作詞 : 黃家駒 [00:18.580]今天我 寒夜里看雪飄過(guò) [00:25.050]懷著冷卻了的心窩漂遠(yuǎn)方 [00:30.990]風(fēng)雨里追趕 "
在page外定義函數(shù):
以]劃分?jǐn)?shù)組 第二部分就是歌詞內(nèi)容:item.split("]")[1] 第一部分即為對(duì)應(yīng)的時(shí)間:item.split("]")[0]
// 獲取歌詞 function getlyric(id,cb) { console.log("id:",id) let url = `http://neteasemusic.leanapp.cn/lyric` wx.request({ url: url, data: { id: id }, method: "GET", // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT // header: {}, // 設(shè)置請(qǐng)求的 header success: function (res) { // success if (!res.data.lrc.lyric) return false; let lyric = res.data.lrc.lyric let timearr = lyric.split("[") let obj = {} let lyricArr=[] // seek 為鍵 歌詞為value timearr.forEach((item) => { let key = parseInt(item.split("]")[0].split(":")[0]) * 60 + parseInt(item.split("]")[0].split(":")[1]) let val = item.split("]")[1] obj[key] = val }) for(let key in obj){ // obj[key] = obj[key].split(" ")[0] lyricArr.push(obj[key]) } cb&&cb(obj,lyricArr) }, fail: function (res) { // fail }, complete: function (res) { // complete } }) }
在page中調(diào)用:傳入歌曲ID(上文我們已經(jīng)存入緩存,在緩存中取出即可),和將其設(shè)置在data的回調(diào)
getlyric(id,function(data, lyricArr){ that.setData({ lyricobj:data, lyricArr:lyricArr }) })
wxml進(jìn)行渲染:
{{item}}
添加歌曲:
我的可以在本地緩存中添加兩個(gè)key入對(duì)應(yīng)的信息
like:我的喜歡
recent:最近
選擇事件
radioChange: function(e) { console.log("radio發(fā)生change事件,攜帶value值為:", e.detail.value) this.setData({ percent:"100%" }) }, //radio發(fā)生change事件,攜帶value值為: like //radio發(fā)生change事件,攜帶value值為: recent
點(diǎn)擊添加按鈕,向上呼出選項(xiàng),將當(dāng)前播放的歌曲設(shè)置到對(duì)應(yīng)的數(shù)組即可
進(jìn)行當(dāng)前歌曲的播放:
頁(yè)面onshow的時(shí)候,獲取本地緩存的信息,在success的回調(diào)中,設(shè)置到data,以供頁(yè)面解析,而后在獲取歌詞的函數(shù)中也進(jìn)行一次回調(diào),設(shè)置歌詞,
播放本地音樂(lè),播放成功之后,在success的回調(diào)中,獲取正在播放的音樂(lè)信息,包括該歌曲的總時(shí)長(zhǎng),再進(jìn)行設(shè)置。
onShow: function () { var that = this; console.log("正在播放 is on show") // 獲取緩存 wx.getStorage({ key: "clickdata", success: function (res) { var value = res.data var id = value.id if (value) { // 設(shè)置到data that.setData({ id:id, name: value.name, src: value.mp3Url, poster: value.picUrl, author: value.singer }) getlyric(id,function(data, lyricArr){ that.setData({ lyricobj:data, lyricArr:lyricArr }) }) } let url = that.data.src || value.mp3Url; // 播放 wx.playBackgroundAudio({ dataUrl: value.mp3Url, title: value.name, coverImgUrl: value.picUrl, success: function () { wx.hideLoading() console.log("url",url) setTimeout(function(){ wx.getBackgroundAudioPlayerState({ success: function (res) { var tempduration = res.duration console.log("get bg success", tempduration, res) // 設(shè)置時(shí)長(zhǎng) that.setData({ sumduration: tempduration }) }, complete: function (res) { console.log(" get bg complete:", res) } }) },1000) }, complete:function(){ // 獲取正在播放的信息 console.log("play",url) } }) } }) },
這樣我們不知不覺(jué)進(jìn)入多個(gè)回調(diào)嵌套的問(wèn)題
代碼優(yōu)化,使用Promise,較為優(yōu)雅地解決回調(diào)小程序暫時(shí)不支持async await
在 common.js 中為小程序提供的api上裹上一層Promise,并且通過(guò)module.exports = operation暴露出去
const operation = { getMusicData: function () { return new Promise((resolve, reject) => { wx.getBackgroundAudioPlayerState({ success: function (res) { resolve(res); }, fail: function (err) { reject(err); } }) }) }, // 播放音樂(lè) 參數(shù):url title 圖片url playMusic: function (url, title, pic) { return new Promise((resolve, reject) => { wx.playBackgroundAudio({ dataUrl: url, title: title, coverImgUrl: pic, success: function () { resolve(true) }, fail: function () { reject(new Error("播放錯(cuò)誤")); } }) }) }, asyncGetStorage: function (key) { return new Promise((resolve, reject) => { wx.getStorage({ key: key, success: function (res) { resolve(res.data) }, fail: function (err) { reject(err) } }) }) }, getlyric: function (id) { return new Promise((resolve, reject) => { console.log("id:", id) let url = `http://neteasemusic.leanapp.cn/lyric` wx.request({ url: url, data: { id: id }, method: "GET", // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT // header: {}, // 設(shè)置請(qǐng)求的 header success: function (res) { // success if (!res.data.lrc.lyric) return false; let lyric = res.data.lrc.lyric let timearr = lyric.split("[") let obj = {} let lyricArr = [] // seek 為鍵 歌詞為value timearr.forEach((item) => { let key = parseInt(item.split("]")[0].split(":")[0]) * 60 + parseInt(item.split("]")[0].split(":")[1]) let val = item.split("]")[1] obj[key] = val }) for (let key in obj) { // obj[key] = obj[key].split(" ")[0] lyricArr.push(obj[key]) } // cb && cb(obj, lyricArr) resolve(lyricArr) }, fail: function (err) { reject(err) }, complete: function (res) { // complete } }) }) } } module.exports = operation
重寫(xiě)一下當(dāng)前歌曲播放事件
onShow: function () { let that = this; Common.asyncGetStorage("clickdata")//本地緩存 .then(data => { // console.log(data) if (!data) return; that.setData({ id: data.id, name: data.name, src: data.mp3Url, poster: data.picUrl, author: data.singer }) return Common.playMusic(data.mp3Url, data.name, data.picUrl); }) .then(status => { if(!status) return; wx.hideLoading(); console.log("id,",that.data.id) return Common.getlyric(that.data.id) }) .then((lyricArr) => { console.log("lyricArr",lyricArr) that.setData({ lyricArr: lyricArr }) return Common.getMusicData() }) .then(data => { let tempduration = data.duration console.log("get bg success", tempduration, data) // 設(shè)置時(shí)長(zhǎng) that.setData({ sumduration: tempduration }) }) },
這樣即可縮減部分代碼。
有幫助可以Star>github源碼18屆小前端求職中["html/html5", "css/css3", "js/es5/es6", "node"]
1424254461@qq.com
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/82972.html
awesome-github-wechat-weapp 是由OpenDigg整理并維護(hù)的微信小程序開(kāi)源項(xiàng)目庫(kù)集合。我們會(huì)定期同步上的項(xiàng)目到這里,也歡迎各位 UI組件開(kāi)發(fā)框架實(shí)用庫(kù)開(kāi)發(fā)工具服務(wù)端項(xiàng)目實(shí)例Demo UI組件 weui-wxss ★1873 - 同微信原生視覺(jué)體驗(yàn)一致的基礎(chǔ)樣式庫(kù)zanui-weapp ★794 - 好用易擴(kuò)展的小程序 UI 庫(kù)wx-charts ★449 - 微信小程...
摘要:項(xiàng)目主要是微信小程序也用到了等。前端部分主要是歌曲播放控制和交互部分的代碼,更多關(guān)于小程序的內(nèi)容可見(jiàn)微信小程序開(kāi)發(fā)文檔小程序框架結(jié)構(gòu)微信小程序的入口是根目錄下的它們分別描述的小程序的主題邏輯和公共配置部分。 剛進(jìn)公司不久,因?yàn)楣静块T(mén)年后業(yè)務(wù)拓展的關(guān)系,可能在年后會(huì)被分配到公司的微信公眾號(hào)組做小程序相關(guān)的開(kāi)發(fā)工作,因此寫(xiě)了個(gè)微信小程序wx-audio踩坑。目前還有一些功能沒(méi)有寫(xiě)完:如返...
摘要:下一步準(zhǔn)備使用網(wǎng)易云代替音樂(lè)。已經(jīng)開(kāi)發(fā)新的網(wǎng)易云代替音樂(lè)了,需要的可以看看這篇文章為微信小程序開(kāi)發(fā)的網(wǎng)易云音樂(lè)庫(kù) 項(xiàng)目要做一個(gè)可以為日記添加音樂(lè)的小程序,所以要用到音樂(lè)api,參考了一些文章后我們封裝了一個(gè)qq音樂(lè)api庫(kù)(完成了動(dòng)態(tài)token獲取,音樂(lè)搜索,音樂(lè)專輯圖片,音樂(lè)名稱,歌手名稱,播放),有需要的可以到Github自提。 小程序qq音樂(lè)api庫(kù)Gihub地址https://...
摘要:并總結(jié)經(jīng)典面試題集各種算法和插件前端視頻源碼資源于一身的文檔,優(yōu)化項(xiàng)目,在瀏覽器端的層面上提升速度,幫助初中級(jí)前端工程師快速搭建項(xiàng)目。 本文是關(guān)注微信小程序的開(kāi)發(fā)和面試問(wèn)題,由基礎(chǔ)到困難循序漸進(jìn),適合面試和開(kāi)發(fā)小程序。并總結(jié)vue React html css js 經(jīng)典面試題 集各種算法和插件、前端視頻源碼資源于一身的文檔,優(yōu)化項(xiàng)目,在瀏覽器端的層面上提升速度,幫助初中級(jí)前端工程師快...
閱讀 1504·2021-10-11 10:59
閱讀 1876·2021-09-09 11:36
閱讀 1383·2019-08-30 15:55
閱讀 1327·2019-08-29 11:20
閱讀 3063·2019-08-26 13:39
閱讀 1466·2019-08-26 13:37
閱讀 1957·2019-08-26 12:11
閱讀 1324·2019-08-23 14:28