要求
1.页面包含一个音乐列表,点击列表中的音乐可以播放对应的音乐。
2.播放中的音乐在列表中有标识,并且可以暂停或继续播放。
3.显示当前音乐的播放进度和总时长,并可以拖动进度条调整播放进度。
4.点击切换按钮可以切换到下一首音乐。
5.点击循环按钮可以切换音乐的播放模式(单曲循环、列表循环、随机播放)。
代码实现
wxml 文件
<view class="container"> <scroll-view scroll-y class="music-list"> <view wx:for="{{ musicList }}" wx:key="{{ index }}" class="music-item" bindtap="onMusicTap" data-index="{{ index }}"> <view class="music-name">{{ item.name }}</view> <view class="music-artist">{{ item.artist }}</view> </view> </scroll-view> <audio id="audio" src="{{ currentMusic.src }}" bindtimeupdate="onTimeUpdate" bindended="onEnded"></audio> <view class="player"> <view class="controls"> <button class="control-btn" bindtap="onPrev">上一首</button> <button class="control-btn" bindtap="onPlayOrPause">{{ playing ? '暂停' : '播放' }}</button> <button class="control-btn" bindtap="onNext">下一首</button> <button class="control-btn" bindtap="onChangeMode">模式</button> </view> <view class="progress"> <text>{{ currentTime }}</text> <slider max="{{ duration }}" value="{{ currentPosition }}" bindchange="onSliderChange" /> <text>{{ durationStr }}</text> </view> </view> </view>
wxss 文件
.container { padding: 20rpx; } .music-list { height: 300rpx; } .music-item { padding: 10rpx; border-bottom: 1rpx solid #eee; text-align: left; } .player { margin-top: 20rpx; display: flex; flex-direction: column; align-items: center; } .controls { display: flex; justify-content: space-around; width: 100%; margin-bottom: 10rpx; } .control-btn { background-color: #009688; color: #fff; padding: 10rpx 20rpx; border-radius: 4rpx; } progress { display: flex; align-items: center; } .slider { flex: 1; margin: 0 10rpx; }
js文件
Page({ data: { musicList: [ { name: '歌曲1', artist: '歌手1', src: 'music1.mp3' }, { name: '歌曲2', artist: '歌手2', src: 'music2.mp3' }, // 更多音乐... ], currentMusic: {}, playing: false, duration: 0, currentPosition: 0, currentTime: '00:00', durationStr: '00:00', playMode: 0, // 0: 列表循环,1: 单曲循环,2: 随机播放 }, onMusicTap(e) { const index = e.currentTarget.dataset.index; const music = this.data.musicList[index]; this.setData({ currentMusic: music, playing: true, }); this.playMusic(); }, onPlayOrPause() { if (this.data.playing) { this.pauseMusic(); } else { this.playMusic(); } }, playMusic() { const audio = this.selectComponent('#audio'); audio.play(); this.setData({ playing: true, }); }, pauseMusic() { const audio = this.selectComponent('#audio'); audio.pause(); this.setData({ playing: false, }); }, onPrev() { let currentIndex = this.data.musicList.findIndex(item => item.src === this.data.currentMusic.src); if (currentIndex === 0) { currentIndex = this.data.musicList.length - 1; } else { currentIndex--; } const music = this.data.musicList[currentIndex]; this.setData({ currentMusic: music, playing: true, }); this.playMusic(); }, onNext() { let currentIndex = this.data.musicList.findIndex(item => item.src === this.data.currentMusic.src); if (currentIndex === this.data.musicList.length - 1) { currentIndex = 0; } else { currentIndex++; } const music = this.data.musicList[currentIndex]; this.setData({ currentMusic: music, playing: true, }); this.playMusic(); }, onTimeUpdate(e) { const duration = e.detail.duration; const currentPosition = e.detail.currentTime; const currentTime = this.formatTime(currentPosition); const durationStr = this.formatTime(duration); this.setData({ duration: duration, currentPosition: currentPosition, currentTime: currentTime, durationStr: durationStr, }); }, onEnded() { if (this.data.playMode === 1) { // 单曲循环 const audio = this.selectComponent('#audio'); audio.seek(0); audio.play(); } else { this.onNext(); } }, onSliderChange(e) { const value = e.detail.value; const audio = this.selectComponent('#audio'); audio.seek(value); }, onChangeMode() { let playMode = this.data.playMode; playMode = (playMode + 1) % 3; this.setData({ playMode: playMode, }); }, formatTime(time) { const minutes = Math.floor(time / 60); const seconds = Math.floor(time % 60); const minuteStr = minutes < 10 ? '0' + minutes : '' + minutes; const secondStr = seconds < 10 ? '0' + seconds : '' + seconds; return minuteStr + ':' + secondStr; }, });
解析
其中,onPrev() 和 onNext() 函数实现了切换到上一首和下一首音乐的逻辑。通过 findIndex()
函数找到当前音乐在列表中的位置,然后根据播放模式计算出下一首或上一首音乐的位置,更新当前音乐并播放。
onTimeUpdate() 函数实现了更新播放进度的逻辑,通过 detail 参数获取音频的总时长和当前播放进度,并格式化成 00:00
的形式,更新页面数据。
onEnded() 函数实现了音乐播放结束的逻辑,根据当前的播放模式决定是单曲循环还是切换到下一首音乐。
onSliderChange() 函数实现了调整播放进度的逻辑,通过 seek() 函数跳转到指定的时间点。
onChangeMode() 函数实现了切换播放模式的逻辑,通过取余操作循环切换三种播放模式。
到这里也就结束了,希望对您有所帮助。