微信小程序?qū)崙?zhàn)之網(wǎng)易云音樂歌曲詳情頁實(shí)現(xiàn)代碼
這里記錄一下做網(wǎng)易云小程序的音樂播放詳情頁面的代碼。
音樂播放界面的主要的重點(diǎn)有幾個(gè):
1、磁盤和搖桿的旋轉(zhuǎn)效果,這里運(yùn)用了css的動(dòng)畫屬性
2、音樂播放和暫停,下一首/上一首等播放效果的實(shí)現(xiàn)
3、進(jìn)度條的樣式和控制
4、和上一頁音樂推薦列表頁通信,利用訂閱與發(fā)布Pubsub
HTML代碼及要點(diǎn)
<!--pages/songDetail/songDetail.wxml--> <view class="songDetailContainer"> <view class="author">{{song.ar[0].name}}</view> <view class="circle"></view> <image class="needle {{isPlay?'needleRotate':''}}" src="/static/images/song/needle.png"></image> <view class="discContainer {{isPlay?'discAnimation':''}}"> <image class="disc" src="/static/images/song/disc.png"></image> <image class="musicImg" src="{{song.al.picUrl}}"></image> </view> <!-- 進(jìn)度條控制區(qū)域 --> <view class="progressControl"> <text>{{currentTime}}</text> <!-- 總進(jìn)度條 --> <view class="barControl"> <!-- 實(shí)時(shí)進(jìn)度條 --> <view class="audio-currentTime-Bar" style="width: {{currentWidth + 'rpx'}}"> <!-- 小圓球 --> <view class="audio-circle"></view> </view> </view> <text>{{durationTime}}</text> </view> <!-- 底部控制播放區(qū)域 --> <view class="musicControl"> <text class="iconfont icon-iconsMusicyemianbofangmoshiShuffle"></text> <text class="iconfont icon-shangyishou" id="pre" bindtap="handleSwitch"></text> <text class="iconfont {{isPlay?'icon-zanting': 'icon-bofang'}} big" bindtap="handleMusicPlay"></text> <text class="iconfont icon-next" id="next" bindtap="handleSwitch"></text> <text class="iconfont icon-iconsMusicyemianbofangmoshiPlayList"></text> </view> </view>
HTML要點(diǎn):
這里利用了三元表達(dá)式,當(dāng)isPlay為true時(shí),搖桿、磁盤和播放按鈕就會(huì)開始啟動(dòng)動(dòng)畫,否則相反。
實(shí)時(shí)進(jìn)度條的動(dòng)畫利用了紅色實(shí)時(shí)進(jìn)度條的寬度的變化風(fēng)格。
CSS代碼及要點(diǎn)
/* pages/songDetail/songDetail.wxss */ @import "/static/iconfont/iconfont.wxss"; page { height: 100%; } .songDetailContainer{ height: 100%; background: rgba(0,0,0,0.5); display: flex; flex-direction: column; align-items: center; } /* 底座 */ .circle { position: relative; z-index: 100; width: 60rpx; height: 60rpx; border-radius: 50%; background: #fff; margin: 10rpx 0; } /* 搖桿 */ .needle{ position: relative; z-index: 99; top:-40rpx; left: 60rpx; width:192rpx; height:274rpx; /* 要先設(shè)置好旋轉(zhuǎn)的中心點(diǎn) */ transform-origin:40rpx 0; transform: rotate(-20deg); transition: transform 1s; } /* 播放時(shí)搖桿動(dòng)畫 */ .needleRotate{ transform: rotate(0deg); } /* 磁盤 */ .discContainer{ position: relative; top:-170rpx; width: 598rpx; height: 598rpx; } .discAnimation{ animation: disc 3s linear infinite; animation-delay:1s; } /* @keyframes:設(shè)置動(dòng)畫幀 1、from to 使用于簡單的動(dòng)畫,只有起始幀和結(jié)束幀 2、百分比 多用于復(fù)雜的動(dòng)畫,動(dòng)畫不止兩幀 */ @keyframes disc{ from{ transform: rotate(0deg); } to{ transform: rotate(360deg); } } .disc{ width: 598rpx; height: 598rpx; } .musicImg{ position: absolute; top:0; right:0; bottom:0; left:0; margin: auto; width: 370rpx; height: 370rpx; border-radius: 50%; } /* 底部控制區(qū)域 */ .musicControl { position: absolute; bottom: 40rpx; left: 0; border-top: 1rpx solid #fff; width: 100%; display: flex; } .musicControl text { width: 20%; height: 120rpx; line-height: 120rpx; text-align: center; color: #fff; font-size: 50rpx; } .musicControl text.big{ font-size: 80rpx; } /* 進(jìn)度條控制區(qū)域 */ .progressControl { position: absolute; bottom: 200rpx; width: 640rpx; height: 80rpx; line-height: 80rpx; display: flex; } .barControl { position: relative; width: 450rpx; height: 4rpx; background: rgba(0, 0, 0, 0.4); margin: auto; } .audio-currentTime-Bar { position: absolute; top: 0; left: 0; z-index: 1; height: 4rpx; background: red; } /* 小圓球 */ .audio-circle { position: absolute; right: -12rpx; top: -4rpx; width: 12rpx; height: 12rpx; border-radius: 50%; background: #fff; }
CSS要點(diǎn):
這里利用了transform動(dòng)畫,首先設(shè)置好旋轉(zhuǎn)的中心點(diǎn),利用transform-origin屬性, 上方圖片紅框代表搖桿圖片的范圍,藍(lán)色點(diǎn)為需要旋轉(zhuǎn)的中心點(diǎn),位置為x坐標(biāo)為40rpx,縱坐標(biāo)為0。搖桿要從原來的圖片位置逆時(shí)針轉(zhuǎn)動(dòng)20度,所以設(shè)定為transform:rotate(-20deg)。加上過渡效果,利用transition:transform 1s。
磁盤的轉(zhuǎn)動(dòng)利用了css里的animation,linear代表線性,infinite代表一直動(dòng)。
要設(shè)置動(dòng)畫幀@keyframes,從0度到360度,代表了磁盤的旋轉(zhuǎn)。
JS代碼及要點(diǎn)
// pages/songDetail/songDetail.js import request from '../../../utils/request' import PubSub from 'pubsub-js' import moment from 'moment' //獲取全局實(shí)例 const appInstance = getApp(); Page({ /** * 頁面的初始數(shù)據(jù) */ data: { isPlay:false, //播放狀態(tài) song:{},//歌曲詳情對象 musicId:'', //音樂id musicLink:'',//音樂的鏈接 currentTime:'00:00',//實(shí)時(shí)時(shí)間 durationTime:'00:00',//總時(shí)長 currentWidth:0, //實(shí)時(shí)進(jìn)度條寬度 }, /** * 生命周期函數(shù)--監(jiān)聽頁面加載 */ onLoad: function (options) { //options:用于接收路由跳轉(zhuǎn)的query參數(shù) //原生小程序中路由傳參,對參數(shù)的長度有限制,如果長度過長會(huì)自動(dòng)截取掉 // console.log(options) // console.log(musicId) let musicId = options.musicId; this.setData({ musicId }) //獲取音樂詳情 this.getMusicInfo(musicId); /** * 問題:如果用戶操作系統(tǒng)的控制音樂播放/暫停的按鈕,頁面不知道,導(dǎo)致頁面是否播放的狀態(tài)和真實(shí)的音樂播放狀態(tài)不一致 * 解決方案: * 通過控制音頻的實(shí)例backgroundAudioManager 去監(jiān)視音樂暫停播放/暫停 */ //判斷當(dāng)前頁面音樂是否在播放 if(appInstance.globalData.isMusicPlay && appInstance.globalData.musicId === musicId){ //修改當(dāng)前頁面音樂播放狀態(tài)為true this.setData({ isPlay:true }) } //創(chuàng)建控制音樂播放的實(shí)例 this.backgroundAudioManager = wx.getBackgroundAudioManager(); //監(jiān)視音樂播放/暫停/停止 this.backgroundAudioManager.onPlay(()=>{ //修改音樂是否播放的狀態(tài) this.changePlayState(true); //修改全局音樂播放的狀態(tài) appInstance.globalData.musicId = musicId; }); this.backgroundAudioManager.onPause(() => { this.changePlayState(false); }); this.backgroundAudioManager.onStop(() => { this.changePlayState(false); }); //監(jiān)聽音樂自然播放結(jié)束 this.backgroundAudioManager.onEnded(() => { //自動(dòng)切換至下一首音樂,并且自動(dòng)播放 PubSub.publish('switchType','next') //將實(shí)時(shí)進(jìn)度條還原成0 this.setData({ currentWidth:0, currentTime: '00:00' }) }) //監(jiān)聽音樂實(shí)時(shí)播放的進(jìn)度 this.backgroundAudioManager.onTimeUpdate(()=>{ //格式化實(shí)時(shí)播放時(shí)間 let currentTime = moment(this.backgroundAudioManager.currentTime*1000).format('mm:ss') let currentWidth = this.backgroundAudioManager.currentTime / this.backgroundAudioManager.duration*450 this.setData({ currentTime, currentWidth }) }) }, //修改播放狀態(tài)的功能函數(shù) changePlayState(isPlay){ this.setData({ isPlay }) //修改全局音樂播放的狀態(tài) appInstance.globalData.isMusicPlay = isPlay; }, //獲取音樂詳情的功能函數(shù) async getMusicInfo(musicId){ let songData = await request('/song/detail',{ids:musicId}); //songData.songs[0].dt 單位ms let durationTime = moment(songData.songs[0].dt).format('mm:ss') this.setData({ song:songData.songs[0], durationTime }) //動(dòng)態(tài)修改窗口標(biāo)題 wx.setNavigationBarTitle({ title:this.data.song.name }) }, //點(diǎn)擊播放/暫停的回調(diào) handleMusicPlay(){ let isPlay = !this.data.isPlay; // //修改是否播放的狀態(tài) // this.setData({ // isPlay // }) let {musicId,musicLink} = this.data; this.musicControl(isPlay,musicId,musicLink); }, //控制音樂播放/暫停的功能函數(shù) async musicControl(isPlay, musicId, musicLink){ if(isPlay){ //音樂播放 if(!musicLink){ //獲取音樂播放鏈接 let musicLinkData = await request('/song/url', { id: musicId }); musicLink = musicLinkData.data[0].url; this.setData({ musicLink }) } this.backgroundAudioManager.src = musicLink; this.backgroundAudioManager.title = this.data.song.name; }else{ //暫停音樂 this.backgroundAudioManager.pause(); } }, //點(diǎn)擊切換上一首下一首的回調(diào) handleSwitch(event){ //獲取切歌的類型 let type = event.currentTarget.id; //關(guān)閉當(dāng)前播放的音樂 this.backgroundAudioManager.stop() //訂閱來自recommendsong頁面發(fā)布的musicId消息 PubSub.subscribe('musicId',(msg,musicId)=>{ // console.log(musicId) //獲取音樂詳情信息 this.getMusicInfo(musicId) //自動(dòng)播放切換的當(dāng)前音樂 this.musicControl(true,musicId) //取消訂閱 PubSub.unsubscribe('musicId') }) //發(fā)布消息數(shù)據(jù)給recommendSong PubSub.publish('switchType',type) }, })
JS要點(diǎn):
全局?jǐn)?shù)據(jù)放在app.js中:
這里利用了
到此這篇關(guān)于微信小程序?qū)W習(xí)】網(wǎng)易云音樂歌曲詳情頁代碼實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)微信小程序網(wǎng)易云音樂詳情頁內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
微信小程序?qū)崿F(xiàn)文字長按復(fù)制與一鍵復(fù)制功能全過程
微信小程序開發(fā)是依托微信的,所以他的代碼是嵌入在微信的原始代碼之中的,這篇文章主要給大家介紹了關(guān)于微信小程序?qū)崿F(xiàn)文字長按復(fù)制與一鍵復(fù)制功能的相關(guān)資料,需要的朋友可以參考下2023-03-03JavaScript中的一些實(shí)用小技巧總結(jié)
這篇文章主要給大家總結(jié)介紹了關(guān)于JavaScript中的一些實(shí)用小技巧,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用JavaScript具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04JavaScript彈簧振子超簡潔版 完全符合能量守恒,胡克定理
完全符合能量守恒,胡克定理的JavaScript彈簧振子(超簡潔版,超越第一版!)2009-10-10詳解JavaScript到TypeScript的轉(zhuǎn)換過程
JavaScript是一門強(qiáng)大而靈活的編程語言,TypeScript作為JavaScript的超集,為開發(fā)人員提供了靜態(tài)類型檢查、更好的協(xié)作能力和面向?qū)ο缶幊痰闹С郑疚膶⒃敿?xì)講解如何將JavaScript代碼轉(zhuǎn)換為TypeScript,并寫一些代碼示例參考2023-06-06JavaScript本地存儲與會(huì)話存儲的實(shí)現(xiàn)介紹
本地存儲和會(huì)話存儲是比較常用的方法,你知道兩者的區(qū)別嗎,本文詳細(xì)的介紹了JavaScript中本地存儲(LocalStorage)和會(huì)話存儲(SessionStorage)的使用,具有一定的參考價(jià)值,感興趣的可以了解一下2022-08-08JavaScript中關(guān)鍵字?var、let、const的區(qū)別詳解
在JavaScript中,var、let和const是用于聲明變量的關(guān)鍵字,它們之間存在一些區(qū)別,這篇文章就給大家詳細(xì)介紹一下它們之間的區(qū)別,文章通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2023-08-08JavaScript實(shí)現(xiàn)網(wǎng)頁端播放攝像頭實(shí)時(shí)畫面
這篇文章主要介紹了如何利用JavaScript實(shí)現(xiàn)在網(wǎng)頁端播放局域網(wǎng)(不能上云)或是廣域網(wǎng)的攝像頭的實(shí)時(shí)畫面,文中的示例代碼講解詳細(xì),需要的可以參考一下2022-02-02