当前位置:网站首页>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 )
边栏推荐
- 多商户商城系统功能拆解15讲-平台端会员标签
- 申请SSL证书,并给域名配置SSL证书,并部署服务器;SSL证书的下载和安装
- 通用测试用例写作规范
- 1311_ Hardware design_ Summary of ICT concept, application, advantages and disadvantages
- tf.truncated_ Normal() usage
- What is the problem of the time series database that has been developed for 5 years?
- 1311_硬件设计_ICT概念、应用以及优缺点学习小结
- laravel8 实现接口鉴权封装使用JWT
- Save the image with gaussdb (for redis), and the recommended business can easily reduce the cost by 60%
- [unity3d shader] character projection and reflection
猜你喜欢

《opencv学习笔记》-- 重映射

E-commerce operator Xiaobai, how to get started quickly and learn data analysis?

基于Caffe ResNet-50网络实现图片分类(仅推理)的实验复现

The convolution kernel is expanded to 51x51, and the new CNN architecture slak counterattacks the transformer

涂鸦幻彩产品开发包如何使用

Idea2020.3.1 cannot be opened (double click cannot be opened), but it can be opened through idea.bat.

booking.com缤客上海面经
![[programmers must] Tanabata confession strategy:](/img/55/0b43dd18c8682250db13ad94cd2c2c.png)
[programmers must] Tanabata confession strategy: "the moon meets the cloud, the flowers meet the wind, and the night sky is beautiful at night". (with source code Collection)

How to choose sentinel vs hystrix?

Hcip day 14
随机推荐
Data elements
Leetcode: 102. Sequence traversal of binary tree
【程序员必备】七夕表白攻略:”月遇从云,花遇和风,晚上的夜空很美“。(附源码合集)
IDEA2020.3.1不能打开(双击不能打开),但可以通过idea.bat打开。
[create interactive dice roller application]
php 查找 session 存储文件位置的方法
想要做好软件测试,可以先了解AST、SCA和渗透测试
Hcip day 14
Tf.constant usage
深度学习之SuperViT
STM32状态机编程实例——全自动洗衣机(下)
How to use graffiti magic color product development kit
Dracoo master
Leetcode-202. happy number
[mathematical modeling - Summary of planning model] | matlab solution
触觉智能分享-RK3568在景区导览机器人中的应用
Failed to install the hcmon driver
div设置高度不生效
Aike AI frontier promotion (7.18)
waf详解