当前位置:网站首页>Wechat applet realizes music player (5)
Wechat applet realizes music player (5)
2022-07-26 03:52:00 【richest_ qi】
List of articles
Antecedents feed
pubsubjs Realize page communication
npm install --save pubsub-js, Install third party libraries pubsub-js.import PubSub from "pubsub-js", Introducing third-party libraries pubsub.- Subscribe to news :
id = PubSub.subscribe( Message name ,callback), And callback The first parameter of the default is the message name , Then there are the parameters passed in by the developer . - Release the news :
PubSub.publish( Message name , Developer parameters ). - Unsubscribe :
PubSub.unsubscribe(id).
moment.js Realize time formatting
This example will use a third-party library moment.js To format the time .
- Installation dependency .
npm install --save moment. - Wechat developer tools , Tools > structure npm.
- Introduce and use... In the page moment.
import moment from "moment";moment( Time ).format( Format );
BackgroundAudioManager
BackgroundAudioManager, It is the only background audio manager in the world . The applet cuts into the background , If the audio is playing , You can continue playing . But the background state cannot be called API Manipulate the playback state of audio .
From wechat client 6.7.2 Version start , If you need the applet to cut the background and continue to play the audio , Need to be in the global configuration file app.json Middle configuration requiredBackgroundModes attribute , Such as :"requiredBackgroundModes": ["audio"].
BackgroundAudioManager example , Can pass wx.getBackgroundAudioManager() obtain .BackgroundAudioManager The instance has the following properties and methods :
title, Audio title , Required .src, Audio data source , The default is an empty string , Not required . however , Only setsrcwhen , The audio will play automatically .duration, The length of the current audio ,number type , Unit is s, That is, seconds .currentTime, The current audio playback position ,number type , Unit is s, That is, seconds .play(), Play music .pause(), Music suspended .onPlay(function callback), Listen for background audio playback events .onPause(function callback), Listen for background audio pause events .onStop(function callback), Listen for background audio stop event .onEnded(function callback), Monitor the end event of natural playback of background audio .onTimeUpdate(function callback), Listen for background audio playback progress update events .
Applet project
The main files involved in the code are :
- app.json
- app.wxss
- app.js
- pages/index/index.json
- pages/index/index.wxml
- pages/index/index.wxss
- pages/index/index.js
- pages/music/music.json
- pages/music/music.wxml
- pages/music/music.wxss
- pages/music/music.js

app.json
{
"pages": [
"pages/index/index",
"pages/music/music"
],
"window": {
"navigationBarBackgroundColor": "#624d2e",
"navigationBarTitleText": " home page ",
"navigationBarTextStyle": "white"
},
"requiredBackgroundModes": [
"audio"
],
"style": "v2",
"sitemapLocation": "sitemap.json"
}
app.wxss
page{
height: 100%;
}
app.js
App({
globalData:{
isPlayGlobal:false, // Is there a song currently playing
musicIdGlobal:'' // Which song is currently playing
}
})
pages/index/index.json
{
"usingComponents": {
},
"navigationBarTitleText": " Playlist "
}
pages/index/index.wxml
<view class="index-container">
<view class="header">
<image src="/static/images/icon-play-square.png"></image>
<text> Play all </text>
<text>{
{musicList.length}}</text>
</view>
<scroll-view class="music-list" enable-flex scroll-y >
<view class="music-item" wx:for="{
{musicList}}" wx:key="id" bindtap="handleTap" data-musicindex="{
{index}}" data-musicitem="{
{item}}">
<view class="music-index">{
{index+1}}</view>
<image class="music-image" src="{
{item.picUrl}}"></image>
<view class="music-info">
<view class="musci-name">{
{item.name}}</view>
<view class="music-author">{
{item.author}}</view>
</view>
<image class="btn-more" src="/static/images/icon-more.png"></image>
</view>
</scroll-view>
</view>
pages/index/index.wxss
.index-container{
padding: 20rpx;
background:#624d2e
}
.header{
display: flex;
align-items: center;
}
.header image{
width: 28rpx;
height: 28rpx;
margin-right: 20rpx;
}
.header text{
color: #fff;
height: 28rpx;
line-height: 28rpx;
margin-right: 20rpx;
font-size: 28rpx;
}
.music-list{
margin-top: 20rpx;
color: #fff;
height: calc(100vh - 88rpx);
}
.music-item{
display: flex;
align-items: center;
height: 100rpx;
margin: 20rpx 0;
position: relative;
}
.music-item .music-index{
width: 50rpx;
font-size: 28rpx;
color: #aaa;
}
.music-item .music-image{
width: 80rpx;
height: 80rpx;
border-radius: 6rpx;
margin-right: 20rpx;
}
.music-item .music-info{
display: flex;
flex-direction: column;
}
.music-item .music-info .music-author{
font-size: 24rpx;
color: #aaa;
margin-top: 10rpx;
}
.music-item .btn-more{
width: 36rpx;
height: 36rpx;
position: absolute;
right: 0;
}
pages/index/index.js
import PubSub from "pubsub-js";
const host = "http://localhost:3000";
Page({
data:{
musicList:[], // Song list
musicindex:0 // After entering a song , Record the index of the song in the list
},
onLoad(){
this.getDataFromServer();
// receive messages , Receive from page pages/music/music The news of , according to “ On a ”or“ The following piece ”, Determine which song should be displayed currently
PubSub.subscribe("switchsong",(msgName,type) => {
// console.log(msgName,type);
let {
musicindex,musicList} = this.data;
if(type === "prev"){
if(musicindex===0) {
musicindex = musicList.length-1;
}else{
musicindex--;
}
}else if(type === "next"){
if(musicindex === musicList.length-1){
musicindex = 0;
}else{
musicindex++;
}
}
this.setData({
musicindex});
const music = musicList[musicindex];
// Send a message , Tell page pages/music/music, Tell it the details of the song after switching .
PubSub.publish("refreshmusic",music);
})
},
getDataFromServer(){
const result = [
{
id:"001",name:" In torrential rain ","author":" Li Ruoxi ","picUrl":host+"/images/ In torrential rain .jpg","url":host+"/audios/ In torrential rain .mp3",duration:161000},
{
id:"002",name:"Last Dance","author":" Five hundred ","picUrl":host+"/images/Last Dance.jpg","url":host+"/audios/Last Dance.mp3",duration:271000},
{
id:"003",name:" The king and the beggar ","author":" Hua Chenyu ","picUrl":host+"/images/ The king and the beggar .jpg","url":host+"/audios/ The king and the beggar .mp3",duration:178000},
{
id:"004",name:" Chilo Levis reply ","author":" Xue Kaiqi ","picUrl":host+"/images/ Chilo Levis reply .jpg","url":host+"/audios/ Chilo Levis reply .mp3",duration:243000},
{
id:"005",name:" Red sun ","author":" Li Keqin ","picUrl":host+"/images/ Red sun .jpg","url":host+"/audios/ Red sun .mp3",duration:291000},
{
id:"006",name:" Happy worship ","author":" Wilber Pan Zhang Shaohan ","picUrl":host+"/images/ Happy worship .jpg","url":host+"/audios/ Happy worship .mp3",duration:329000},
{
id:"007",name:" The door is unlocked ","author":" Huangpinguan ","picUrl":host+"/images/ The door is unlocked .jpg","url":host+"/audios/ The door is unlocked .mp3",duration:233000},
{
id:"008",name:" Just love you ","author":" David Tao ","picUrl":host+"/images/ Just love you .jpg","url":host+"/audios/ Just love you .mp3",duration:340000},
{
id:"009",name:" Happy little frog ","author":" Liu Shiming ","picUrl":host+"/images/ Happy little frog .jpg","url":host+"/audios/ Happy little frog .mp3",duration:130000},
{
id:"0010",name:" Years of friendship ","author":" Jordan Chan Zheng Yijian Thank God Lin Xiaofeng Qian Jiale ","picUrl":host+"/images/ Years of friendship .jpg","url":host+"/audios/ Years of friendship .mp3",duration:209000},
{
id:"0011",name:" gentle ","author":" May day ","picUrl":host+"/images/ gentle .jpg","url":host+"/audios/ gentle .mp3",duration:269000}
];
this.setData({
musicList:result});
},
handleTap(event){
const {
musicitem,musicindex} = event.currentTarget.dataset;
this.setData({
musicindex})
wx.navigateTo({
url: '/pages/music/music?musicitem='+JSON.stringify(musicitem),
})
}
})
pages/music/music.json
{
"usingComponents": {
},
"navigationBarBackgroundColor": "#2f434e",
"navigationBarTitleText": " Music details "
}
pages/music/music.wxml
<view class="music-container">
<view class="music-name">{
{music.name}}</view>
<view class="music-author">{
{music.author}}</view>
<image class="arm {
{isPlay&&'arm-reset'}}" src="/static/images/arm.png"></image>
<view class="disc-container {
{isPlay&&'disc-animate'}}">
<image class="disc" src="/static/images/disc.png"></image>
<image class="music-image" src="{
{music.picUrl}}"></image>
</view>
<view class="progress-container">
<text class="current-time">{
{fmtCurrentTime}}</text>
<view class="bar-box">
<view class="current-progress" style="width:{
{
currentWidth}}rpx">
<view class="progress-circle"></view>
</view>
</view>
<text class="duration">{
{fmtDuration}}</text>
</view>
<view class="player">
<view class="btns">
<image class="loop-btn" src="/static/images/loop.png"></image>
<image class="prev-btn" src="/static/images/prev.png" id="prev" bindtap="handleSwitch"></image>
<image class="play-btn" src="{
{isPlay?'/static/images/stop.png':'/static/images/play.png'}}" bindtap="handlePlay"></image>
<image class="next-btn" src="/static/images/next.png" id="next" bindtap="handleSwitch"></image>
<image class="list-btn" src="/static/images/list.png"></image>
</view>
</view>
</view>
pages/music/music.wxss
.music-container{
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
background: #2f434e;
position: relative;
}
.music-container .music-name{
margin: 10rpx 0;
color: #fff;
font-size: 36rpx;
}
.music-container .music-author{
color: #bbb;
font-size: 28rpx;
margin: 6rpx 0;
}
.music-container .arm{
width:204rpx;
height: 358rpx;
position: relative;
left: 72rpx;
z-index: 99;
transform: rotate(-15deg);
transform-origin: 30rpx 30rpx;
transition: transform .7s linear;
}
.disc-container{
position: relative;
top: -128rpx;
width: 490rpx;
height: 490rpx;
}
.disc-container .disc{
width: 100%;
height: 100%;
}
.disc-container .music-image{
width: 270rpx;
height: 270rpx;
border-radius: 100%;
position: absolute;
left: 0;right: 0;top: 0;bottom: 0;
margin: auto;
}
.music-container .arm-reset{
transform: rotate(0deg);
}
.disc-animate{
animation: rotate 2.5s 1s linear infinite;
}
@keyframes rotate{
from{
transform: rotate(0deg);
}
to{
transform: rotate(360deg);
}
}
.player{
width: 100%;
position: absolute;
bottom: 60rpx;
}
.btns{
display: flex;
align-items: center;
justify-content: space-evenly;
}
.btns image{
width: 36rpx;
height: 36rpx;
}
.btns .play-btn,.btns .stop-btn{
width: 90rpx;
height: 90rpx;
}
.progress-container {
width: 100%;
display: flex;
justify-content: space-around;
align-items: center;
}
.progress-container .bar-box{
width: 456rpx;
height: 4rpx;
line-height: 4rpx;
background: #888;
}
.bar-box .current-progress{
position: relative;
height: 4rpx;
line-height: 4rpx;
background: #fff;
}
.progress-circle{
width: 16rpx;
height: 16rpx;
border-radius: 50%;
background: #fff;
position: absolute;
right: -16rpx;
top: -6rpx;
}
.progress-container text{
color: #ccc;
font-size: 22rpx;
margin: 0 40rpx;
}
pages/music/music.js
import PubSub from "pubsub-js";
import moment from 'moment';
const appInstance = getApp();
Page({
data:{
isPlay:false,
music:{
},
fmtDuration:"00:00",
fmtCurrentTime:"00:00",
currentWidth:0
},
onLoad(options){
const music = JSON.parse(options.musicitem);
let fmtDuration = moment(music.duration).format("mm:ss");
this.setData({
music,fmtDuration})
const {
isPlayGlobal,musicIdGlobal} = appInstance.globalData;
const {
id} = this.data.music;
if(isPlayGlobal && musicIdGlobal === id) {
this.setData({
isPlay:true});
}
this.bam = wx.getBackgroundAudioManager();
this.bam.onPlay(() => {
this.setData({
isPlay:true})
appInstance.globalData.isPlayGlobal = true;
appInstance.globalData.musicIdGlobal = this.data.music.id;
})
this.bam.onPause(() => {
this.setData({
isPlay:false})
appInstance.globalData.isPlayGlobal = false;
})
this.bam.onStop(() => {
this.setData({
isPlay:false})
appInstance.globalData.isPlayGlobal = false;
})
this.bam.onEnded(() => {
// this.setData({isPlay:false});
// appInstance.globalData.isPlayGlobal = false;
// The music naturally ends , Then switch to the next song
PubSub.publish("switchsong","next");
// receive messages , Receive from pages/index/index The news of , Show the song details after switching
const eventId = PubSub.subscribe("refreshmusic",(msgName,music) => {
PubSub.unsubscribe(eventId);
this.setData({
music})
this.musicControl();
const fmtDuration = moment(this.data.music.duration).format("mm:ss");
this.setData({
fmtDuration,fmtCurrentTime:"00:00"})
})
})
this.bam.onTimeUpdate(() => {
const currentWidth = Math.floor(456 * this.bam.currentTime / this.bam.duration);
const fmtCurrentTime = moment(this.bam.currentTime * 1000).format("mm:ss");
this.setData({
currentWidth,fmtCurrentTime});
})
},
handlePlay(){
const isPlay = !this.data.isPlay;
this.setData({
isPlay});
this.musicControl();
},
musicControl(){
const {
isPlay} = this.data;
if(isPlay){
this.bam.src = this.data.music.url;
this.bam.title = this.data.music.name;
}else{
this.bam.pause();
}
},
handleSwitch(event){
const type = event.target.id;
// Send a message , tell pages/index/index: Cut one or the next .prev Represents cutting a song ,next Represents cutting off a song .
PubSub.publish("switchsong",type);
// receive messages , Receive from pages/index/index The news of , Show the song details after switching
const eventId = PubSub.subscribe("refreshmusic",(msgName,music) => {
PubSub.unsubscribe(eventId);
this.setData({
music})
this.musicControl();
})
}
})
Related links
moment.js Chinese document
pubsubjs
Wechat applet realizes music player (4)( Use pubsubjs Realize inter page communication )
边栏推荐
- Can UDP and TCP use the same port?
- IDEA2020.3.1不能打开(双击不能打开),但可以通过idea.bat打开。
- 中国数据库 OceanBase 入选 Forrester Translytical 数据平台报告
- MySQL索引失效场景以及解决方案
- 全校软硬件基础设施一站式监控 ,苏州大学以时序数据库替换 PostgreSQL
- Chinese database oceanbase was selected into the Forrester translational data platform report
- PHP connects to MySQL database, and database connects to static tool classes to simplify the connection.
- bond网络模式配置
- CPU and GPU are out of date, and the era of NPU and APU begins
- 微信小程序实现音乐播放器(4)(使用pubsubjs实现页面间通信)
猜你喜欢

加班一周开发了报表系统,这个低代码免费IT报表神器太好用了

Why are more and more users of Bing search?

A large factory developed and tested one, and strangled its neck with a mouse line

Analysis on the infectious problem of open source license

某大厂开发和测试干了一架,还用鼠标线勒脖子...

KBPC1510-ASEMI大芯片15A整流桥KBPC1510

ZK snark: about private key, ring signature, zkksp

基于移位寄存器的同步FIFO

Experimental reproduction of image classification (reasoning only) based on caffe resnet-50 network

If you want to do a good job in software testing, you can first understand ast, SCA and penetration testing
随机推荐
php 实现从1累加到100的算法
容器跑不动?网络可不背锅
括号嵌套问题(建议收藏)
PHP连接mysql数据库,数据库连接静态工具类,简化连接。
《opencv学习笔记》-- 重映射
Find my technology | the Internet of things asset tracking market has reached US $6.6 billion, and find my helps the market develop
微信小程序实现音乐播放器(4)(使用pubsubjs实现页面间通信)
How to use graffiti magic color product development kit
redis集群的三种方式
研发了 5 年的时序数据库,到底要解决什么问题?
Idea2020.3.1 cannot be opened (double click cannot be opened), but it can be opened through idea.bat.
软考 系统架构设计师 简明教程 | 案例分析解题技巧
Why are more and more users of Bing search?
Connect external MySQL databases in istio Service Grid
资深报表开发经验总结:明白这一点,没有做不好的报表
按键消抖的Verilog实现
PHP 对象转换数组
Kbpc1510-asemi large chip 15A rectifier bridge kbpc1510
How does redis implement persistence? Explain the AOF trigger mechanism and its advantages and disadvantages in detail, and take you to quickly master AOF
Opencv learning notes -- Hough transform