这里记录一下做网易云小程序的音乐播放详情页面的代码。
音乐播放界面的主要的重点有几个:
1、磁盘和摇杆的旋转效果,这里运用了css的动画属性
2、音乐播放和暂停,下一首/上一首等播放效果的实现
3、进度条的样式和控制
4、和上一页音乐推荐列表页通信,利用订阅与发布Pubsub

HTML代码及要点
- <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>
-
- <view class="progressControl">
- <text>{{currentTime}}</text>
-
- <view class="barControl">
-
- <view class="audio-currentTime-Bar" style="width: {{currentWidth + 'rpx'}}">
-
- <view class="audio-circle"></view>
- </view>
- </view>
- <text>{{durationTime}}</text>
- </view>
-
- <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要点:



这里利用了三元表达式,当isPlay为true时,摇杆、磁盘和播放按钮就会开始启动动画,否则相反。

实时进度条的动画利用了红色实时进度条的宽度的变化风格。
CSS代码及要点
CSS要点:


这里利用了transform动画,首先设置好旋转的中心点,利用transform-origin属性, 上方图片红框代表摇杆图片的范围,蓝色点为需要旋转的中心点,位置为x坐标为40rpx,纵坐标为0。摇杆要从原来的图片位置逆时针转动20度,所以设定为transform:rotate(-20deg)。加上过渡效果,利用transition:transform 1s。

磁盘的转动利用了css里的animation,linear代表线性,infinite代表一直动。
要设置动画帧@keyframes,从0度到360度,代表了磁盘的旋转。
JS代码及要点
- // pages/songDetail/songDetail.js
- import request from '../../../utils/request'
- import PubSub from 'pubsub-js'
- import moment from 'moment'
- //获取全局实例
- const appInstance = getApp();
- Page({
- /**
- * 页面的初始数据
- */
- data: {
- isPlay:false, //播放状态
- song:{},//歌曲详情对象
- musicId:'', //音乐id
- musicLink:'',//音乐的链接
- currentTime:'00:00',//实时时间
- durationTime:'00:00',//总时长
- currentWidth:0, //实时进度条宽度
- },
- /**
- * 生命周期函数--监听页面加载
- */
- onLoad: function (options) {
- //options:用于接收路由跳转的query参数
- //原生小程序中路由传参,对参数的长度有限制,如果长度过长会自动截取掉
-
- // console.log(options)
- // console.log(musicId)
- let musicId = options.musicId;
- this.setData({
- musicId
- })
- //获取音乐详情
- this.getMusicInfo(musicId);
- /**
- * 问题:如果用户操作系统的控制音乐播放/暂停的按钮,页面不知道,导致页面是否播放的状态和真实的音乐播放状态不一致
- * 解决方案:
- * 通过控制音频的实例backgroundAudioManager 去监视音乐暂停播放/暂停
- */
- //判断当前页面音乐是否在播放
- if(appInstance.globalData.isMusicPlay && appInstance.globalData.musicId
- === musicId){
- //修改当前页面音乐播放状态为true
- this.setData({
- isPlay:true
- })
- }
- //创建控制音乐播放的实例
- this.backgroundAudioManager = wx.getBackgroundAudioManager();
- //监视音乐播放/暂停/停止
- this.backgroundAudioManager.onPlay(()=>{
- //修改音乐是否播放的状态
- this.changePlayState(true);
- //修改全局音乐播放的状态
- appInstance.globalData.musicId = musicId;
- });
- this.backgroundAudioManager.onPause(() => {
- this.changePlayState(false);
- });
- this.backgroundAudioManager.onStop(() => {
- this.changePlayState(false);
- });
- //监听音乐自然播放结束
- this.backgroundAudioManager.onEnded(() => {
- //自动切换至下一首音乐,并且自动播放
- PubSub.publish('switchType','next')
- //将实时进度条还原成0
- this.setData({
- currentWidth:0,
- currentTime: '00:00'
- })
- })
- //监听音乐实时播放的进度
- this.backgroundAudioManager.onTimeUpdate(()=>{
- //格式化实时播放时间
- let currentTime = moment(this.backgroundAudioManager.currentTime*1000).format('mm:ss')
- let currentWidth = this.backgroundAudioManager.currentTime / this.backgroundAudioManager.duration*450
- this.setData({
- currentTime,
- currentWidth
- })
- })
- },
- //修改播放状态的功能函数
- changePlayState(isPlay){
- this.setData({
- isPlay
- })
- //修改全局音乐播放的状态
- appInstance.globalData.isMusicPlay = isPlay;
- },
- //获取音乐详情的功能函数
- 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
- })
- //动态修改窗口标题
- wx.setNavigationBarTitle({
- title:this.data.song.name
- })
- },
- //点击播放/暂停的回调
- handleMusicPlay(){
- let isPlay = !this.data.isPlay;
- // //修改是否播放的状态
- // this.setData({
- // isPlay
- // })
- let {musicId,musicLink} = this.data;
- this.musicControl(isPlay,musicId,musicLink);
- },
-
- //控制音乐播放/暂停的功能函数
- 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();
- }
- },
- //点击切换上一首下一首的回调
- handleSwitch(event){
- //获取切歌的类型
- let type = event.currentTarget.id;
- //关闭当前播放的音乐
- this.backgroundAudioManager.stop()
- //订阅来自recommendsong页面发布的musicId消息
- PubSub.subscribe('musicId',(msg,musicId)=>{
- // console.log(musicId)
-
- //获取音乐详情信息
- this.getMusicInfo(musicId)
- //自动播放切换的当前音乐
- this.musicControl(true,musicId)
- //取消订阅
- PubSub.unsubscribe('musicId')
- })
- //发布消息数据给recommendSong
- PubSub.publish('switchType',type)
- },
- })
复制代码 JS要点:
全局数据放在app.js中:


这里利用了
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |