微信小程序——音乐播放器

embedded/2024/10/10 21:45:20/

一、界面设计

  1. 播放页面:

    • 显示当前播放歌曲的封面图片、歌曲名称、歌手名称。
    • 有播放 / 暂停按钮、上一首、下一首按钮。
    • 进度条显示播放进度,可以拖动进度条调整播放位置。
    • 音量调节滑块。
  2. 歌曲列表页面:

    • 展示歌曲列表,包括歌曲名称、歌手名称和封面图片(可选)。
    • 点击歌曲可以切换播放。

二、功能实现

  1. 数据存储与获取:

    • 可以将歌曲信息存储在小程序的本地缓存或使用云开发数据库存储歌曲列表。
    • 通过网络请求获取歌曲资源的 URL。
  2. 播放控制:

    • 使用小程序的音频 API 进行播放控制。
    • 实现播放、暂停、上一首、下一首等功能。
    • 监听音频播放进度,更新进度条。
  3. 进度条控制:

    • 允许用户拖动进度条来调整播放位置。
    • 根据用户操作更新音频的播放位置。
  4. 音量调节:

    • 通过滑块控制音频的音量大小。
  5. 歌曲列表切换:

    • 在歌曲列表页面点击歌曲时,切换当前播放歌曲。
    • 更新播放页面的歌曲信息。

目的

  1. 掌握swiper组件、scroll-view组件的使用
  2. 掌握image组件的使用
  3. 掌握音频API的使用
  4. 掌握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) % 60return (minute < 10 ? '0' + minute : minute) + ':' + (second < 10 ? '0' + second : second)}},// 音乐播放setMusic: function(index) {var music = this.data.playlist[index]this.audioCtx.src = music.srcthis.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 + 1this.setMusic(index)if (this.data.state === 'running') {this.play()}},// 滚动条调节歌曲进度sliderChange: function(e) {var second = e.detail.value * this.audioCtx.duration / 100this.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}
}


http://www.ppmy.cn/embedded/125553.html

相关文章

Vue.js 中<teleport> 组件,<Suspense> 组件

一、&#xff1c;teleport&#xff1e; 组件 在 Vue.js 中&#xff0c;<teleport> 是一个非常强大的内置组件&#xff0c;用于将子组件或元素“传送”到 DOM 中的不同位置&#xff0c;而不仅限于它们在父组件中的结构。这可以帮助解决许多布局和样式方面的问题&…

zotero主页面显示的标签名与信息处的标签名不一致

问题描述&#xff1a;我在网页导入了论文之后&#xff0c;自动匹配了一些该论文的信息&#xff0c;但是很多都是空的&#xff0c;最大的问题就是找不到出版物的信息&#xff1b; 解决&#xff1a;最后发现在信息中是叫刊名&#xff0c;其中年对应的是在日期部分&#xff1b; 极…

java项目之美食推荐商城的设计与实现源码(springboot+vue+mysql)

项目简介 美食推荐商城的设计与实现实现了以下功能&#xff1a; 美食推荐商城的设计与实现的主要使用者分为&#xff1a; 管理员在后台主要管理购物车管理、字典管理、公告信息管理、留言板管理、美食管理、美食收藏管理、美食评价管理、美食订单管理、商家管理、用户管理、管…

需求9——通过一个小需求来体会service层的作用

昨天在完成了睿哥的需求验收之后&#xff0c;暂时没有其他任务&#xff0c;因此今天可能会比较有空闲时间。趁着这个机会&#xff0c;我打算把之前完成的一些需求进行总结&#xff0c;方便以后复习和参考。 在8月份的时候&#xff0c;我负责了一个需求&#xff0c;该需求的具体…

Java API接口开发规范

文章目录 一、命名规范1.1 接口命名1.2 变量命名 二、接收参数规范2.1 请求体&#xff08;Body&#xff09;2.2 查询参数&#xff08;Query Parameters&#xff09; 三、参数检验四、接收方式规范五、异常类处理六、统一返回格式的定义七、API接口的幂等性&#xff08;Idempote…

网 络 安 全

网络安全是指保护网络系统及其所存储或传输的数据免遭未经授权访问、使用、揭露、破坏、修改或破坏的实践和技术措施。网络安全涉及多个方面&#xff0c;包括但不限于以下几个方面&#xff1a; 1. 数据保护&#xff1a;确保数据在传输和存储过程中的完整性和保密性&#xff0c;…

基于深度学习的复杂器官建模与模拟

基于深度学习的复杂器官建模与模拟是一项前沿技术&#xff0c;它利用深度学习模型从大量医学图像和临床数据中提取信息&#xff0c;生成复杂器官的三维结构模型&#xff0c;并对其进行功能模拟。这项技术对于医学诊断、手术规划、药物开发和疾病研究有重要意义&#xff0c;特别…

MySQL - 索引

索引&#xff08;index&#xff09;是帮助数据库高效获取数据的数据结果。 优点&#xff1a; 提高数据查询的效率&#xff0c;降低数据库的IO成本通过索引列对数据进行排序&#xff0c;降低数据排序的成本&#xff0c;降低CPU消耗 缺点&#xff1a; 索引会占用存储空间索引…