小程序简单版音乐播放器
小程序简单版音乐播放器

结构
先来看看页面结构
<!-- 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/02.jpg" mode="aspectFill" /></swiper-item><swiper-item><image src="/images/03.jpg" mode="aspectFill" /></swiper-item><swiper-item><image src="/images/04.jpg" mode="aspectFill" /></swiper-item></swiper><!-- 功能按钮 --><view class="content-info-portal"><view><image src="/images/04.png" mode="aspectFill" catch:tap="fm" /><text>私人FM</text></view><view><image src="/images/05.png" mode="aspectFill" /><text>每日歌曲推荐</text></view><view><image src="/images/06.png" mode="aspectFill" /><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/hush.png" mode="aspectFill" /><view>Hush</view></view><view class="list-item"><image src="/images/talk.png" mode="aspectFill" /><view>Talk</view></view><view class="list-item"><image src="/images/men.png" mode="aspectFill" /><view>Memories</view></view><view class="list-item"><image src="/images/hour.png" mode="aspectFill" /><view>golden hour</view></view><view class="list-item"><image src="/images/mess.png" mode="aspectFill" /><view>Yes I'm A Mess</view></view><view class="list-item"><image src="/images/iii.png" mode="aspectFill" /><view>III Do It</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}}" mode="aspectFill" /><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="changePage" data-page="2" mode="aspectFill" /><!-- 播放或暂停 --><image wx:if="{{state=='paused'}}" src="/images/02.png" bindtap="play" mode="aspectFill" /><image wx:else src="/images/02stop.png" bindtap="pause" mode="aspectFill" /><!-- 下一曲 --><image src="/images/03.png" bindtap="next" mode="aspectFill" /></view>
</view>
其中一些代码可以使用 wx:for 循环创建,这边为了简单明了就没有循环创建
页面样式
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;
}
核心代码
音乐数据
🆗,接下来创建播放列表数据
data: {item: 0,tab: 0,// 播放列表数据playlist: [{id: 1,title: 'Always Online',singer: '林俊杰',src: 'http://localhost:3000/林俊杰 - Always Online.mp3',coverImgUrl: '/images/jj.jpeg'}, {id: 2,title: '不得不爱',singer: '潘玮柏、弦子',src: 'http://localhost:3000/潘玮柏、弦子 - 不得不爱.mp3',coverImgUrl: '/images/pwb.jpg'}, {id: 3,title: '大城小爱',singer: '王力宏',src: 'http://localhost:3000/王力宏 - 大城小爱.mp3',coverImgUrl: '/images/wlh.jpeg'}, {id: 4,title: '偏爱',singer: '张芸京',src: 'http://localhost:3000/张芸京 - 偏爱.mp3',coverImgUrl: '/images/pa.jpeg'}],state: 'paused',playIndex: 0,play: {currentTime: '00:00',duration: '00:00',percent: 0,title: '',singer: '',coverImgUrl: '/images/cover.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 () {})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()}
🆗,最后的就剩下node服务了,这边node服务只是为了挂载音乐文件这些静态资源。
这边我也会将服务端上传到本篇博客,把自己需要的MP3或MP4格式文件放入到htdocs中即可。
这边怕引起版权纠纷和维权问题就不把歌曲文件放入其中

node 下面代码存放在 index.js 中 请记得使用 yarn 或者 npm 安装以下的引入文件
var express = require('express')
var serveIndex = require('serve-index')
var serveStatic = require('serve-static')
var multiparty = require('multiparty')
var finalhandler = require('finalhandler')
var util = require('util')var LOCAL_BIND_PORT = 3000
var app = express()app.post('/upload', function (req, res) {var form = new multiparty.Form()form.encoding = 'utf-8'form.uploadDir = './htdocs/upfile'form.maxFilesSize = 4 * 1024 * 1024form.parse(req, function (err, fields, files) {if (err) {console.log('parse error: ' + err)} else {console.log('parse files: ' + JSON.stringify(files))}res.writeHead(200, { 'content-type': 'text/plain;charset=utf-8' })res.write('received upload')res.end()})
})var serve = serveStatic('./htdocs')
app.use('/', serveIndex('./htdocs', { 'icons': true }))app.get('/*', function (req, res) {serve(req, res, finalhandler(req, res))
});// console.log(`Start static file server at ::${LOCAL_BIND_PORT}, Press ^ + C to exit`)
console.log('启动成功')app.listen(LOCAL_BIND_PORT)
// 监听3000端口
// app.listen(3000, () => {
// console.log('server running at http://127.0.0.1:3000')
// })
最后附上完整代码
// pages/index/index.js
Page({/*** 页面的初始数据*/data: {item: 0,tab: 0,// 播放列表数据playlist: [{id: 1,title: 'Always Online',singer: '林俊杰',src: 'http://localhost:3000/林俊杰 - Always Online.mp3',coverImgUrl: '/images/jj.jpeg'}, {id: 2,title: '不得不爱',singer: '潘玮柏、弦子',src: 'http://localhost:3000/潘玮柏、弦子 - 不得不爱.mp3',coverImgUrl: '/images/pwb.jpg'}, {id: 3,title: '大城小爱',singer: '王力宏',src: 'http://localhost:3000/王力宏 - 大城小爱.mp3',coverImgUrl: '/images/wlh.jpeg'}, {id: 4,title: '偏爱',singer: '张芸京',src: 'http://localhost:3000/张芸京 - 偏爱.mp3',coverImgUrl: '/images/pa.jpeg'}],state: 'paused',playIndex: 0,play: {currentTime: '00:00',duration: '00:00',percent: 0,title: '',singer: '',coverImgUrl: '/images/cover.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 () {})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()}
})

- 失联
最后编辑时间 2024,06,17;10:11
相关文章:
小程序简单版音乐播放器
小程序简单版音乐播放器 结构 先来看看页面结构 <!-- wxml --><!-- 标签页标题 --> <view class"tab"><view class"tab-item {{tab0?active:}}" bindtap"changeItem" data-item"0">音乐推荐</view><…...
驾校预约管理系统
摘 要 随着驾驶技术的普及和交通安全意识的增强,越来越多的人选择参加驾校培训,以获取驾驶执照。然而,驾校管理面临着日益增长的学员数量和繁琐的预约管理工作。为了提高驾校的管理效率和服务质量,驾校预约管理系统成为了必不可少…...
C++ 左值右值 || std::move() || 浅拷贝,深拷贝 || 数据类型
数据类型: 作用:决定变量所占内存空间的字节大小,和布局方式基本数据类型: 算数类型: 整形(bool / char……扩展集 / int / long……)&& 浮点形(float/double……ÿ…...
发那科机器人IO 分配
IO 信号 也称为输入\输出信号,是机器人与外围设备通信的电信号...
ubuntu开机怎么进入、退出命令行界面
要在Ubuntu系统开机时进入命令行界面,可以按照以下步骤操作: 在开机过程中按下Ctrl Alt F1组合键,这将会切换到第一个虚拟控制台,即命令行界面。如果Ctrl Alt F1没有生效,也可以尝试Ctrl Alt F2、Ctrl Alt F3…...
『FPGA通信接口』LVDS接口(4)LVDS接收端设计
文章目录 1.LVDS接收端概述2逻辑框图3.xapp855训练代码解读4.接收端发送端联调5.传送门 1.LVDS接收端概述 接收端的传输模型各个属性应该与LVDS发送端各属性一致,例如,如果用于接收CMOS图像传感器的图像数据,则接收端程序的串化因子、通道个…...
面试题:HTTP的body是二进制还是文本
实际上,HTTP的body可以是二进制数据,也可以是文本。HTTP协议本身不对body内容的格式做限制,具体格式取决于Content-Type头字段的定义。 文本数据: 当Content-Type头字段指定为文本类型时(如text/plain、text/html、ap…...
5分钟带你部署一套Jenkins持续集成环境
5分钟带你部署一套Jenkins持续集成环境 Jenkins是开源CI&CD软件领导者, 提供超过1000个插件来支持构建、部署、自动化, 满足任何项目的需要。 Jenkins的优点 持续集成和持续交付 作为一个可扩展的自动化服务器,Jenkins 可以用作简单的 CI…...
OpenAI突然宣布停止向中国提供API服务!
标题 🌟 OpenAI突然宣布停止向中国提供API服务! 🌟摘要 📜引言 📢正文 📝1. OpenAI API的重要性2. 停止服务的原因分析3. 对中国市场的影响4. 应对措施代码案例 📂常见问题解答(QA)❓…...
Bootstrap 标签
Bootstrap 标签 引言 Bootstrap 是一个流行的前端框架,它提供了一套丰富的组件和工具,帮助开发者快速构建响应式和移动优先的网页。在 Bootstrap 中,标签(Badge)是一种小巧的组件,用于显示计数、提示或标…...
EtherCAT主站SOEM -- 37 -- win-soem-win10及win11系统QT-SOEM-1个电机转圈圈-周期同步速度模式(CSV模式)
EtherCAT主站SOEM -- 37 -- win-soem-win10及win11系统QT-SOEM-1个电机转圈圈-周期同步速度模式(CSV模式) 0 QT-SOEM及STM32F767-SOEM视频欣赏及源代码链接:0.1 Linux--Ubuntu系统之 QT-SOEM博客、视频欣赏及源代码链接0.2 STM32F767-SOEM 博客、视频欣赏及源代码链接0.3 wi…...
老板舍不得买库存管理软件❓一招解决
在当今快节奏的商业环境中,仓库管理是企业运作中不可或缺的一环。对于许多中小型企业而言,简易且高效的库存管理系统尤为重要。搭贝简易库存管理系统针对仓库的出入库进行有效管理,帮助企业实现库存的透明化和流程的自动化。 客户的痛点 1. …...
【MySQL数据库】:MySQL视图特性
目录 视图的概念 基本使用 准备测试表 创建视图 修改视图影响基表 修改基表影响视图 删除视图 视图规则和限制 视图的概念 视图是一个虚拟表,其内容由查询定义,同真实的表一样,视图包含一系列带有名称的列和行数据。视图中的数据…...
malloc、free和new delete的区别
malloc/free 和 new/delete 是在 C 中分配和释放内存的两种不同方法。它们主要有以下区别: 1. 语法和用法 malloc 和 free: malloc开辟空间时需要手动计算分配的空间大小 int* p (int*)malloc(sizeof(int) * 10); // 分配10个int类型的内存 // 使用内存 free(p); …...
如何有效地优化 Erlang 程序的内存使用,以应对大规模数据处理的需求?
要有效地优化Erlang程序的内存使用,以应对大规模数据处理的需求,可以考虑以下几个方面: 减少不必要的内存分配:避免过多的数据复制和不必要的数据结构创建。可以使用Erlang的二进制数据类型来避免数据复制,使用原子数据…...
vue3项目使用@antv/g6实现可视化流程功能
文章目录 项目需求一、需要解决的问题二、初步使用1.动态数据-组件封装(解决拖拽会留下痕迹的问题,引用图片,在节点右上角渲染图标,实现,事现旋转动画,达到loading效果)2.文本太长,超出部分显示(...),如下函…...
【Linux网络(一)初识计算机网络】
一、网络发展 1.发展背景 2.发展类型 二、网络协议 1.认识协议 2.协议分层 3.OSI七层模型 4.TCP/IP协议 三、网络传输 1.协议报头 2.局域网内的两台主机通信 3.跨网络的两台主机通信 四、网络地址 1.IP地址 2.MAC地址 一、网络发展 1.发展背景 计算机网络的发展…...
Vulhub——Log4j、solr
文章目录 一、Log4j1.1 Apache Log4j2 lookup JNDI 注入漏洞(CVE-2021-44228)1.2 Apache Log4j Server 反序列化命令执行漏洞(CVE-2017-5645) 二、Solr2.1 Apache Solr 远程命令执行漏洞(CVE-2017-12629)2.…...
linux 设置程序自启动
程序随系统开机自启动的方法有很多种, 这里介绍一种简单且常用的, 通过系统的systemd服务进行自启动。 第一步: 新建一个.service文件 sudo vim /etc/systemd/system/myservice.service[Unit] DescriptionMy Service #Afternetwork.target[…...
PostgreSQL 分区表与并行查询(十)
1. 分区表概述 1.1 什么是分区表 分区表是将大表分割成更小、更可管理的部分的技术。每个分区表都可以单独进行索引和查询,从而提高查询性能和管理效率。 1.2 分区策略 1.2.1 基于范围的分区 按照时间范围或者数值范围进行分区,如按月或按地区。 C…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
