微信小程序实现音乐播放器实例完整流程
作者:张謹礧
这篇文章主要介绍了微信小程序实现音乐播放器实例完整流程,通过本章的学习,读者能够掌握小程序的基本交互逻辑的开发,能够运用API来实现项目中的特定功能,学会解决开发过程中常见的问题,需要的朋友可以参考下
目的
- 掌握swiper组件、scroll-view组件的使用
- 掌握image组件的使用
- 掌握音频API的使用
- 掌握slider组件的使用
内容
音乐小程序项目的完整开发流程,其开发步骤包括页面结构的分析、样式的设计、组件的运用等。通过本章的学习,读者能够掌握小程序的基本交互逻辑的开发,能够运用API来实现项目中的特定功能,学会解决开发过程中常见的问题。
代码架构
index.wxml
<!-- 标签页标题 --> <view class="tab"> <view class="tab-item {{tab==0?'active':''}}" bindtap="changeItem" data-item="0">音乐推荐</view> <view class="tab-item {{tab==1?'active':''}}" bindtap="changeItem" data-item="1">播放器</view> <view class="tab-item {{tab==2?'active':''}}" bindtap="changeItem" data-item="2">播放列表</view> </view> <!-- 内容区域 --> <view class="content"> <swiper current="{{item}}" bindchange="changeTab"> <swiper-item> <!-- 内容滚动区域 --> <scroll-view class="content-info" scroll-y> <!-- 轮播图 --> <swiper class="content-info-slide" indicator-color="rgba(255,255,255,.5)" indicator-active-color="#fff" indicator-dots circular autoplay> <swiper-item> <image src="/images/xingong.jpg" /> </swiper-item> <swiper-item> <image src="/images/banner.jpg" /> </swiper-item> <swiper-item> <image src="/images/banner.jpg" /> </swiper-item> </swiper> <!-- 功能按钮 --> <view class="content-info-portal"> <view> <image src="/images/04.png" /> <text>私人FM</text> </view> <view> <image src="/images/05.png" /> <text>每日歌曲推荐</text> </view> <view> <image src="/images/06.png" /> <text>云音乐新歌榜</text> </view> </view> <!-- 热门音乐 --> <view class="content-info-list"> <view class="list-title">推荐歌曲</view> <view class="list-inner"> <view class="list-item"> <image src="/images/图片27.jpg" /> <view>紫罗兰</view> </view> <view class="list-item"> <image src="/images/图片28.jpg" /> <view>五月之歌</view> </view> <view class="list-item"> <image src="/images/图片29.jpg" /> <view>菩提树</view> </view> <view class="list-item"> <image src="/images/图片31.jpg" /> <view>欢乐颂</view> </view> <view class="list-item"> <image src="/images/图片33.jpg" /> <view>安魂曲</view> </view> <view class="list-item"> <image src="/images/图片36.jpg" /> <view>摇篮曲</view> </view> </view> </view> </scroll-view> </swiper-item> <swiper-item> <!-- 播放器页面 --> <include src="play.wxml" /> </swiper-item> <swiper-item> <include src="playlist.wxml" /> </swiper-item> </swiper> </view> <!-- 底部播放器 --> <view class="player"> <image class="player-cover" src="{{play.coverImgUrl}}" /> <view class="player-info"> <view class="player-info-title">{{play.title}}</view> <view class="player-info-singer">{{play.singer}}</view> </view> <view class="player-controls"> <!-- 切换到播放列表 --> <image src="/images/01.png" bindtap="changeItem" data-item="2" /> <!-- 播放或暂停 --> <image wx:if="{{state=='paused'}}" src="/images/02.png" bindtap="play" /> <image wx:else src="/images/02stop.png" bindtap="pause" /> <!-- 下一曲 --> <image src="/images/03.png" bindtap="next" /> </view> </view>
info.wxml
<!-- 内容滚动区域 --> <scroll-view class="content-info" scroll-y> <!-- 轮播图 --> <swiper class="content-info-slide" indicator-color="rgba(255,255,255,.5)" indicator-active-color="#fff" indicator-dots circular autoplay> <swiper-item> <image src="/images/xingong.jpg" /> </swiper-item> <swiper-item> <image src="/images/xingong.jpg" /> </swiper-item> <swiper-item> <image src="/images/banner.jpg" /> </swiper-item> </swiper> <!-- 功能按钮 --> <view class="content-info-portal"> <view> <image src="/images/04.png" /> <text>私人FM</text> </view> <view> <image src="/images/05.png" /> <text>每日歌曲推荐</text> </view> <view> <image src="/images/06.png" /> <text>云音乐新歌榜</text> </view> </view> <!-- 热门音乐 --> <view class="content-info-list"> <view class="list-title">推荐歌曲</view> <view class="list-inner"> <view class="list-item"> <image src="/images/cover.jpg" /> <view>紫罗兰</view> </view> <view class="list-item"> <image src="/images/cover.jpg" /> <view>五月之歌</view> </view> <view class="list-item"> <image src="/images/cover.jpg" /> <view>菩提树</view> </view> <view class="list-item"> <image src="/images/cover.jpg" /> <view>欢乐颂</view> </view> <view class="list-item"> <image src="/images/cover.jpg" /> <view>安魂曲</view> </view> <view class="list-item"> <image src="/images/cover.jpg" /> <view>摇篮曲</view> </view> </view> </view> </scroll-view>
play.wxml
<!-- 播放器 --> <view class="content-play"> <!-- 显示音乐信息 --> <view class="content-play-info"> <text>{{play.title}}</text> <view>—— {{play.singer}} ——</view> </view> <!-- 显示专辑封面 --> <view class="content-play-cover"> <image src="{{play.coverImgUrl}}" style="animation-play-state:{{state}}" /> </view> <!-- 显示播放进度和时间 --> <view class="content-play-progress"> <text>{{play.currentTime}}</text> <view> <slider bindchange="sliderChange" activeColor="#d33a31" block-size="12" backgroundColor="#dadada" value="{{play.percent}}" /> </view> <text>{{play.duration}}</text> </view> </view>
playlist.wxml
<scroll-view class="content-playlist" scroll-y> <view class="playlist-item" wx:for="{{playlist}}" wx:key="id" bindtap="change" data-index="{{index}}"> <image class="playlist-cover" src="{{item.coverImgUrl}}" /> <view class="playlist-info"> <view class="playlist-info-title">{{item.title}}</view> <view class="playlist-info-singer">{{item.singer}}</view> </view> <view class="playlist-controls"> <text wx:if="{{index==playIndex}}">正在播放</text> </view> </view> </scroll-view>
index.js
// pages/index/index.js Page({ /** * 页面的初始数据 */ data: { item: 0, tab: 0, // 播放列表数据 playlist: [{ id: 1, title: '钢琴协奏曲', singer: '肖邦', src: 'http://localhost:3000/1.mp3', coverImgUrl: '/images/cover.jpg' }, { id: 2, title: '奏鸣曲', singer: '莫扎特', src: 'http://localhost:3000/2.mp3', coverImgUrl: '/images/cover.jpg' }, { id: 3, title: '欢乐颂', singer: '贝多芬', src: 'http://localhost:3000/1.mp3', coverImgUrl: '/images/cover.jpg' }, { id: 4, title: '爱之梦', singer: '李斯特', src: 'http://localhost:3000/2.mp3', coverImgUrl: '/images/cover.jpg' }], state: 'paused', playIndex: 0, play: { currentTime: '00:00', duration: '00:00', percent: 0, title: '', singer: '', coverImgUrl: '/images/图片47.jpg', } }, // 页面切换 changeItem: function(e) { this.setData({ item: e.target.dataset.item, }) }, // tab切换 changeTab: function(e) { this.setData({ tab: e.detail.current }) }, // 实现播放器播放功能 audioCtx: null, onReady: function() { this.audioCtx = wx.createInnerAudioContext() // 默认选择第1曲 this.setMusic(0) var that = this // 播放进度检测 this.audioCtx.onError(function() { console.log('播放失败:' + that.audioCtx.src) }) // 播放完成自动换下一曲 this.audioCtx.onEnded(function() { that.next() }) // 自动更新播放进度 this.audioCtx.onPlay(function() {}) // onWaiting触发的暂停 var waitFlag = false // 音频由于网络等原因等待中的回调 this.audioCtx.onWaiting(function() { waitFlag = true }) // 音频准备就绪的回调 this.audioCtx.onCanplay(function() { if (waitFlag) { that.audioCtx.pause() that.audioCtx.play() waitFlag = false } }) this.audioCtx.onTimeUpdate(function() { that.setData({ 'play.duration': formatTime(that.audioCtx.duration), 'play.currentTime': formatTime(that.audioCtx.currentTime), 'play.percent': that.audioCtx.currentTime / that.audioCtx.duration * 100 }) }) // 格式化时间 function formatTime(time) { var minute = Math.floor(time / 60) % 60; var second = Math.floor(time) % 60 return (minute < 10 ? '0' + minute : minute) + ':' + (second < 10 ? '0' + second : second) } }, // 音乐播放 setMusic: function(index) { var music = this.data.playlist[index] this.audioCtx.src = music.src this.setData({ playIndex: index, 'play.title': music.title, 'play.singer': music.singer, 'play.coverImgUrl': music.coverImgUrl, 'play.currentTime': '00:00', 'play.duration': '00:00', 'play.percent': 0 }) }, // 播放按钮 play: function() { this.audioCtx.play() this.setData({ state: 'running' }) }, // 暂停按钮 pause: function() { this.audioCtx.pause() this.setData({ state: 'paused' }) }, // 下一曲按钮 next: function() { var index = this.data.playIndex >= this.data.playlist.length - 1 ? 0 : this.data.playIndex + 1 this.setMusic(index) if (this.data.state === 'running') { this.play() } }, // 滚动条调节歌曲进度 sliderChange: function(e) { var second = e.detail.value * this.audioCtx.duration / 100 this.audioCtx.seek(second) }, // 播放列表换曲功能 change: function(e) { this.setMusic(e.currentTarget.dataset.index) this.play() } })
index.json
{ "navigationBarBackgroundColor": "#fff", "navigationBarTitleText": "音乐", "navigationBarTextStyle": "black" }
index.wxss
page { display: flex; flex-direction: column; background: #17181a; color: #ccc; height: 100%; } .tab { display: flex; } .tab-item { flex: 1; font-size: 10pt; text-align: center; line-height: 72rpx; border-bottom: 6rpx solid #eee; } .content { flex: 1; } .content > swiper { height: 100%; } .player { background: #222; border-top: 1px solid #252525; height: 112rpx; } .tab-item.active { color: #c25b5b; border-bottom-color: #c25b5b; } .content-info { height: 100%; } ::-webkit-scrollbar { width: 0; height: 0; color: transparent; } /* 轮播图 */ .content-info-slide { height: 302rpx; margin-bottom: 20px; } .content-info-slide image { width: 100%; height: 100%; } /* 功能按钮 */ .content-info-portal { display: flex; margin-bottom: 15px; } .content-info-portal > view { flex: 1; font-size: 11pt; text-align: center; } .content-info-portal image { width: 120rpx; height: 120rpx; display: block; margin: 20rpx auto; } /* 热门音乐 */ .content-info-list { font-size: 11pt; margin-bottom: 20rpx; } .content-info-list > .list-title { margin: 20rpx 35rpx; } .content-info-list > .list-inner { display: flex; flex-wrap: wrap; margin: 0 20rpx; } .content-info-list > .list-inner > .list-item { flex: 1; } .content-info-list > .list-inner > .list-item > image { display: block; width: 200rpx; height: 200rpx; margin: 0 auto; border-radius: 10rpx; border: 1rpx solid #555; } .content-info-list > .list-inner > .list-item > view { width: 200rpx; margin: 10rpx auto; font-size: 10pt; } /* 播放器 */ .content-play { display: flex; justify-content: space-around; flex-direction: column; height: 100%; text-align: center; } .content-play-info > view { color: #888; font-size: 11pt; } /* 底部播放器 */ .player { display: flex; align-items: center; background: #222; border-top: 1px solid #252525; height: 112rpx; } .player-cover { width: 80rpx; height: 80rpx; margin-left: 15rpx; border-radius: 8rpx; border: 1px solid #333; } .player-info { flex: 1; font-size: 10pt; line-height: 38rpx; margin-left: 20rpx; padding-bottom: 8rpx; } .player-info-singer { color: #888; } .player-controls image { width: 80rpx; height: 80rpx; margin-right: 15rpx; } /* 显示专辑页面样式 */ .content-play-cover image { animation: rotateImage 10s linear infinite; width: 400rpx; height: 400rpx; border-radius: 50%; border: 1px solid #333; } @keyframes rotateImage { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } /* 播放进度和时间 */ .content-play-progress { display: flex; align-items: center; margin: 0 35rpx; font-size: 9pt; text-align: center; } .content-play-progress > view { flex: 1; } /* 播放列表 */ .playlist-item { display: flex; align-items: center; border-bottom: 1rpx solid #333; height: 112rpx; } .playlist-cover { width: 80rpx; height: 80rpx; margin-left: 15rpx; border-radius: 8rpx; border: 1px solid #333; } .playlist-info { flex: 1; font-size: 10pt; line-height: 38rpx; margin-left: 20rpx; padding-bottom: 8rpx; } .playlist-info-singer { color: #888; } .playlist-controls { font-size: 10pt; margin-right: 20rpx; color: #c25b5b; }
app.json
{ "pages": [ "pages/index/index", "pages/test/index", "pages/test/swiper", "pages/test/test" ], "sitemapLocation": "sitemap.json" }
配置文件
project.config.json
{ "description": "项目配置文件", "packOptions": { "ignore": [], "include": [] }, "setting": { "urlCheck": true, "es6": true, "enhance": true, "postcss": true, "preloadBackgroundData": false, "minified": true, "newFeature": true, "coverView": true, "nodeModules": false, "autoAudits": false, "showShadowRootInWxmlPanel": true, "scopeDataCheck": false, "uglifyFileName": false, "checkInvalidKey": true, "checkSiteMap": true, "uploadWithSourceMap": true, "compileHotReLoad": false, "lazyloadPlaceholderEnable": false, "useMultiFrameRuntime": true, "useApiHook": true, "useApiHostProcess": true, "babelSetting": { "ignore": [], "disablePlugins": [], "outputPath": "" }, "useIsolateContext": true, "userConfirmedBundleSwitch": false, "packNpmManually": false, "packNpmRelationList": [], "minifyWXSS": true, "disableUseStrict": false, "minifyWXML": true, "showES6CompileOption": false, "useCompilerPlugins": false, "ignoreUploadUnusedFiles": true }, "compileType": "miniprogram", "libVersion": "2.23.1", "appid": "wx0298165ccea56bb4", "projectname": "music", "condition": {}, "editorSetting": { "tabIndent": "insertSpaces", "tabSize": 2 } }
到此这篇关于微信小程序实现音乐播放器实例详解的文章就介绍到这了,更多相关小程序实现音乐播放器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!