当前位置:网站首页>Wechat applet music playing code (playing mode, lyrics scrolling)
Wechat applet music playing code (playing mode, lyrics scrolling)
2022-06-10 02:38:00 【Cursive】
When scrolling automatically , The lyrics are too long, causing a long deviation , How to solve :
Every time you scroll , Get the lyrics of the line to be displayed dom Node height position , Scroll directly to the position of the current node .
The formula : Where to scroll = dom Node location - Lyrics area height / 2 - dom The height of the node /2.
Similar functionality : Scroll to middle
Some resources :
dayjs:
https://download.csdn.net/download/qq_42740797/12728688
animate:
https://download.csdn.net/download/qq_42740797/12728700
Project source code :
https://download.csdn.net/download/qq_42740797/15542837
Realized renderings :



wxml:
<view class="container flex-align">
<view style="text-align:center;position:relative;" class="box">
<view style="color:white;">{
{
songs.name}}</view>
<view style="color:#ddd;" class="f12">{
{
songs.ar[0].name}}</view>
<image src="../../images/play/download.png" style="height:60rpx;width:60rpx;" class="download" bindtap="download" />
</view>
<view class="flex-1 flex-center" wx:if="{
{isLrc==false}}" bindtap="isLrc">
<image src="{
{songs.al.picUrl}}" class="img {
{isPlay===false?'pause':''}}" />
</view>
<!-- The lyrics -->
<view wx:else class="flex-1 flex-center z" bindtap="isLrc" style="position:relative;" >
<view wx:if='{
{isScroll}}' class="line flex-box" style="width:100%;color:white;border:1px solid rgba(244,244,244,0.2);">
<view style="margin:0rpx 20rpx;" class="f12 flex-center">{
{
locationShowTime}}</view>
<view class="flex-1" style="color:red;height:2rpx;width:100%;background:green;"></view>
<view style="margin:0rpx 20rpx;" class="flex-center"><image src="../../images/play/locationTime.png" style="height:40rpx;width:40rpx;z-index:999;" catchtap="playScroll"/></view>
</view>
<scroll-view scroll-y style="height:600rpx;" scroll-with-animation scroll-top="{
{locationIndex*27}}" bindscroll="scroll" bindtouchstart="touchstart" bindtouchend="touchend">
<view style="height:284rpx;"></view>
<view wx:for="{
{lrc}}" wx:key="index" class="f14" style="text-align:center;margin:20rpx 0rpx;color:#ccc;{
{location===index?'color:green;':''}}">{
{
item}}</view>
<view style="height:300rpx;"></view>
</scroll-view>
</view>
<!-- Progress bar -->
<view class="flex-box box" style="color:white;">
<view class="flex-center">{
{
nowTime}}</view>
<view class="flex-1">
<slider min="{
{min}}" max="{
{max}}" block-size="12" value="{
{value}}" bindchange="slider" bindchanging="sliderNow"></slider>
</view>
<view class="flex-center">{
{
totalTime}}</view>
</view>
<!-- Playback controls -->
<view class="flex-box menu">
<view>
<image wx:if="{
{categoryActive===0}}" bindtap="toggleCategory" src="../../images/play/list.png" style="height:60rpx;width:60rpx;" />
<image wx:if="{
{categoryActive===1}}" bindtap="toggleCategory" src="../../images/play/rand.png" style="height:60rpx;width:60rpx;" />
<image wx:if="{
{categoryActive===2}}" bindtap="toggleCategory" src="../../images/play/single.png" style="height:60rpx;width:60rpx;" />
</view>
<view>
<image src="../../images/play/back.png" style="height:80rpx;width:80rpx;" bindtap="back" />
</view>
<view>
<image wx:if="{
{isPlay===false}}" bindtap="togglePlay" src="../../images/play/play.png" style="height:100rpx;width:100rpx;" />
<image wx:else bindtap="togglePlay" src="../../images/play/pause.png" style="height:100rpx;width:100rpx;" />
</view>
<view>
<image src="../../images/play/next.png" style="height:80rpx;width:80rpx;" bindtap="next" />
</view>
<view>
<image wx:if="{
{isCollect===false}}" bindtap="toggleCollect" src="../../images/play/collect.png" style="height:60rpx;width:60rpx;" class="move" />
<image wx:else bindtap="toggleCollect" src="../../images/play/collectActive.png" style="height:60rpx;width:60rpx;" class="move" />
</view>
</view>
</view>
<!-- Background image -->
<view class="bgImage">
<image src="{
{songs.al.picUrl}}" />
</view>
js:
import api from "../../http/api"
import dayjs from "../../lib/dayjs.min.js"
let bg=wx.getBackgroundAudioManager();// Background audio manager
let timeId='';// Timer
let lineTimeId='';// Horizontal line timer
let isDelete=false;// Whether to delete the open timer
Page({
data: {
index:-1,// Subscript Song information
ids:[],// song id
songs:{
},// Song details
musics:{
},// song url
lrc:{
},// Song lyrics
// Control properties
isSlider:false,// Whether the progress bar is being dragged
nowTime:"00:00",// Current progress time
totalTime:"00:00",// Total length of time
min:0,// Progress bar start
max:0,// The progress bar ends
value:0,// Progress bar
category:[],// How to play it
categoryActive:0,// Current playback mode 0: Order of play 1: Random broadcast 2: Single tune circulation
isPlay:true,// Do you want to play
isCollect:true,// Whether to collect
// The following lyrics
isLrc:true,// Whether to show the lyrics
lrcArr:[],// Lyrics positioning array
location:0,// Lyrics scroll position
locationIndex:0,//
locationValue:0,// Lyrics scroll to specific position
locationTime:0,// Lyrics location time
locationShowTime:'00:00',// Lyrics positioning display time
isScroll:false,// Scroll through the horizontal lines
},
// Lyrics touch start
touchstart(e){
console.log(" Touch start ",e);
this.setData({
isScroll:true
});
isDelete=false;
if(lineTimeId){
clearTimeout(lineTimeId);
lineTimeId='';
}
},
// Lyrics touch end
touchend(e){
isDelete=true;
console.log(" End of touch ",e);
if(lineTimeId!='')return;
lineTimeId=setTimeout(()=>{
if(isDelete===true){
this.setData({
isScroll:false
});
lineTimeId='';
}
},4000);
},
// Lyrics roll
scroll(e){
if(this.data.isScroll){
let i=parseInt(e.detail.scrollTop/27);
if(!this.data.lrcArr[i])return;// Blank area , There is no time not to execute
console.log(" rolling ",e.detail.scrollTop,this.data.lrcArr[i]);// The interval between lyrics is 27
this.setData({
locationTime:this.data.lrcArr[i],
locationShowTime:dayjs(this.data.lrcArr[i]*1000).format("mm:ss")
});
}
},
// Drag and play lyrics
playScroll(e){
console.log(" Drag to play ",e);
let value=this.data.locationTime;
bg.seek(value);
this.setData({
isScroll:false,
isPlay:true
});
this.update();
},
// Switch whether to display lyrics
isLrc(e){
this.setData({
isLrc:!this.data.isLrc
});
},
// Download Music
download(e){
console.log(e);
wx.setClipboardData({
data: this.data.musics.url,
success:res=>{
console.log(res.data);
wx.hideToast();
wx.showToast({
title: ' Copied link ',
})
}
})
},
// Progress bar drag
sliderNow(e){
console.log(e);
let nowTime=dayjs(e.detail.value*1000).format('mm:ss');
this.setData({
nowTime:nowTime,
isSlider:true
});
},
// Progress bar
slider(e){
console.log(e);
let value=Number(e.detail.value);
let nowTime=dayjs(e.detail.value*1000).format('mm:ss');
this.setData({
value:value,
nowTime:nowTime,
isSlider:false
});
console.log(typeof(value),value);
bg.seek(value);
},
// On a
back(){
let index;
if(this.data.categoryActive===0){
// Order of play
index=this.data.index-1;
if(index<0){
// The first processing
index=this.data.ids.length-1;
}
}else if(this.data.categoryActive===1){
// Random broadcast
index=parseInt(Math.random()*this.data.ids.length);
}else{
// Single tune circulation
index=this.data.index;
bg.stop();
}
console.log(index);
this.setData({
index:index,
isPlay:true
});
this.getData();// Get your music back
},
// The following piece
next(){
let index;
if(this.data.categoryActive===0){
// Order of play
index=this.data.index+1;
if(index===this.data.ids.length){
// The last one deals with
index=0;
}
}else if(this.data.categoryActive===1){
// Random broadcast
index=parseInt(Math.random()*this.data.ids.length);
}else{
// Single tune circulation
index=this.data.index;
bg.stop();
}
console.log(index);
this.setData({
index:index,
isPlay:true
});
this.getData();// Get your music back
},
// Play music
playMusic(){
console.log(" Play ",this.data.musics.url,this.data.songs.name);
bg.src=this.data.musics.url;
bg.title=this.data.songs.name;
// Set progress bar
console.log(" Progress bar ",bg.duration);
},
// Switch playback mode
toggleCategory(e){
// console.log(e);
let i=this.data.categoryActive+1;
if(i>2)i=0;
this.setData({
categoryActive:i
});
},
// Switch play
togglePlay(e){
console.log(e);
this.setData({
isPlay:!this.data.isPlay
});
if(this.data.isPlay){
bg.play();
}else{
bg.pause();
}
},
// Switch favorites
toggleCollect(e){
console.log(e);
this.setData({
isCollect:!this.data.isCollect
});
},
// Get music data
getData(){
let id=this.data.ids[this.data.index];
console.log(id);
// Get song details
api.songDetail(id).then(res=>{
console.log(" Song details :",res);
this.setData({
songs:res.songs[0]
});
// Get music url
api.songUrl(id).then(res=>{
console.log(" Song music url:",res);
this.setData({
musics:res.data[0]
});
this.playMusic();// Play music
wx.hideLoading();
}).catch(err=>{
console.log(err);
});
}).catch(err=>{
console.log(err);
});
// Get the lyrics
api.lyric(id).then(res=>{
console.log(" Song lyrics :",res);
let str=res.lrc.lyric;
let lrcArr=[];
let arr=[];
str=str.split(/\n/g);
str.map(item=>{
let i=item.match(new RegExp("\\[[0-9]*:[0-9]*.[0-9]*\\]","g"));
if(i){
i=i[0].replace('[','').replace(']','')
let time=Number(i.split(':')[0]*60)+Number(i.split(':')[1].split('.')[0]);// millisecond :+Number(i.split(':')[1].split('.')[1]); 01:12.232 ['01','12.232'] ['12','232']
// console.log(time,dayjs(time).format('mm:ss'));
lrcArr.push(time);
arr.push(item.replace(new RegExp("\\[(.*)\\]","g"),""));
}
});
// Go empty
let a1=[],a2=[];
for(let i=0;i<arr.length;i++){
if(arr[i]&&lrcArr[i]){
// Whether there are lyrics at present
a1.push(arr[i]);
a2.push(lrcArr[i]);
}
}
arr=a1,lrcArr=a2;
console.log(arr);
console.log(lrcArr);
this.setData({
lrc:arr,
lrcArr:lrcArr
});
wx.hideLoading();
}).catch(err=>{
console.log(err);
});
},
// Timer update
update(){
if(!this.data.isPlay||this.data.isSlider)return;
let nowTime=bg.currentTime;
let totalTime=bg.duration;
let value=bg.currentTime;
let max=bg.duration;
if(nowTime&&totalTime){
// All have data
// Handle the current position of lyrics
// let len=0;// Lyrics exclude empty subscripts
for(let i=0;i<this.data.lrcArr.length;i++){
if(nowTime>this.data.lrcArr[this.data.lrcArr.length-1]){
// The last lyrics
this.setData({
location:this.data.lrcArr.length-1
});
break;
}
console.log(nowTime,this.data.lrcArr[i]);
if(nowTime>=this.data.lrcArr[i]&&nowTime<this.data.lrcArr[i+1]){
console.log(" Lyrics roll ");
this.setData({
location:i
});
break;
}
}
// Set scrolling
if(this.data.isScroll===false){
this.setData({
locationIndex:this.data.location
});
}
// Processing display
totalTime=dayjs(totalTime*1000).format('mm:ss');
nowTime=dayjs(nowTime*1000).format('mm:ss');
console.log(" Time 2:",totalTime,nowTime);
this.setData({
nowTime:nowTime,
totalTime:totalTime,
max:max,
value:value
});
}
},
onLoad: function (options) {
console.log(options.index,options.ids);
let ids=options.ids.split(',');// String splitting
console.log(ids);
this.setData({
index:Number(options.index),
ids:ids
});
this.getData();
// Background audio
bg.onEnded(()=>{
console.log(" Play finished .");
this.next();
});
bg.onPause(()=>{
console.log(" Pause play ");
this.setData({
isPlay:false
});
});
bg.onPlay(()=>{
console.log(" Start playing ");
this.setData({
isPlay:true
});
});
},
onReady: function () {
},
onShow: function () {
// Set progress bar
timeId=setInterval(()=>{
this.update();
},500);
},
onHide: function () {
},
onUnload: function () {
// Destroy timer
clearInterval(timeId);
},
onPullDownRefresh: function () {
},
onReachBottom: function () {
},
onShareAppMessage: function () {
}
})
wxss:
.container{
position: absolute;
width: 100%;
height:100%;
background:rgba(0,0,0,0.2);
/* border: 1px solid red; */
}
.container>view{
/* border: 1px solid red; */
}
.download{
position: absolute;
right:20rpx;
top: 20rpx;
}
.img{
width:500rpx;
height:500rpx;
border-radius: 50%;
border: 20rpx solid rgba(255,255,255,0.4);
-webkit-animation: rotate 10s linear infinite;
}
.pause{
animation-play-state:paused;
-webkit-animation-play-state:paused; /* Safari and Chrome */
}
.menu{
margin:50rpx 0rpx;
}
.menu>view{
flex:1;
display: flex;
justify-content: center;
align-items: center;
}
.bgImage{
filter:blur(20px);
position:absolute;
height:100%;
width:100%;
z-index: -1;
}
.bgImage>image{
height:100%;
width:100%;
}
.move:active {
animation-delay: -6s;
animation: heartBeat 2s;
}
.line{
position: absolute;
top:50%;
}
@keyframes rotate {
0%{
transform:rotate(0deg);
-ms-transform:rotate(0deg); /* IE 9 */
-moz-transform:rotate(0deg); /* Firefox */
-o-transform:rotate(0deg);
}
100% {
transform:rotate(360deg);
-ms-transform:rotate(360deg); /* IE 9 */
-moz-transform:rotate(360deg); /* Firefox */
-o-transform:rotate(360deg);
}
}
@-webkit-keyframes rotate {
0%{
-moz-transform:rotate(0deg);
}
100%{
-moz-transform:rotate(360deg);
}
}
边栏推荐
- 1、pytorch入门
- pixi. JS drag function
- Electron桌面端开发(能力、如何打包、优势)
- How to take a screenshot of the drop-down menu of the software
- 10个常见触发IO瓶颈的高频业务场景
- 1. Getting started with pytorch
- Two software test questions
- Deepin runs Cherrytree and reports an error. The module gtksourceview2 cannot be found
- Ones Fengbin: from engineer to CTO, with uncertainty and incomplete information | ones talk
- PAT (Advanced Level) Practice 1156 Sexy Primes (试除法)
猜你喜欢

获取省市区列表【项目 商城】

大学生 生活小技巧:利用插件(Tampermonkey )学习网课 | 查题

(W10) prtsc screenshot key cannot be used normally - solution

Explain Seaborn in detail. Just read this one

Double pointer | 27 Removing Elements

3. NLP model

Data product learning - real time computing platform

JDBC introductory exercise, is it caused by the version? What does this error mean?

Eight honors and eight disgraces of programmers' daily development

(w10)Prtsc截图键无法正常使用——解决办法
随机推荐
从进入内核态看内存管理
Array de duplication
第六章 半导体存储器【微机原理】
2022.6.9 C asynchronous
PAT (Advanced Level) Practice 1156 Sexy Primes (试除法)
Screen resolution
Viewing memory management from entering kernel state
Using GDI to realize multi-channel video stream merging
After the SSL certificate is installed, the website still shows insecurity
Cordova development, prompt net:: err_ CLEARTEXT_ NOT_ PERMITTED
uniapp 开发app时获取唯一标识OAID,imei,ooid
Internal resources of stm32
Opengauss "user story" is officially launched! One click to share practical experience, Limited Edition Gift waiting for you
MySQL 8.0.28 installation and configuration tutorial
Lm03 who told you that cross species must be arbitraged?
复杂模型机实验
flutter 双端扫码下载app
latex怎么也不换行,奇怪
Postgresql中如何终止正在执行的查询
Tips for college students' life: using tempermonkey to learn online lessons | check questions