赞
踩
自动滚动时,歌词太长造成了很长的偏移,如何解决:
每次滚动的时候,获取需要展示的那一行歌词的dom节点高度位置,直接滚动到当前节点的位置就可以了。
公式:需要滚动的位置 = dom节点位置 - 歌词区域高度 / 2 - dom节点的高度/2。
类似功能:滚动到中部
项目源码:
https://download.csdn.net/download/qq_42740797/15542837
<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> <!--歌词--> <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;"><text style="position: relative;">{{item}}<text wx:if="{{location===index}}" class="hover" style="animation: test {{timeLen}}s;">{{item}}</text></text></view> <view style="height:300rpx;"></view> </scroll-view> </view> <!--进度条--> <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> <!--播放控件--> <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> <!--背景图片--> <view class="bgImage"> <image src="{{songs.al.picUrl}}" /> </view>
import api from "../../http/api" import dayjs from "../../lib/dayjs.min.js" let bg=wx.getBackgroundAudioManager();//背景音频管理器 let timeId='';//定时器 let lineTimeId='';//水平线定时器 let isDelete=false;//是否删除开启的定时器 Page({ data: { index:-1,//下标 歌曲信息 ids:[],//歌曲id songs:{},//歌曲详情 musics:{},//歌曲url lrc:{},//歌曲歌词 //控件属性 isSlider:false,//是否正在拖动进度条 nowTime:"00:00",//目前进度时间 totalTime:"00:00",//总长度时间 min:0,//进度条开始 max:0,//进度条结束 value:0,//进度条 category:[],//播放方式 categoryActive:0,//当前播放方式 0:顺序播放 1:随机播放 2:单曲循环 isPlay:true,//是否播放 isCollect:true,//是否收藏 //以下歌词 isLrc:true,//是否显示歌词 lrcArr:[],//歌词定位数组 时间 location:0,//歌词滚动位置 locationIndex:0,// locationValue:0,//歌词滚动具体位置 locationTime:0,//歌词定位时间 locationShowTime:'00:00',//歌词定位显示时间 isScroll:false,//滚动显示水平线 timeLen:-1,//文字过渡时间 }, //歌词触碰开始 touchstart(e){ console.log("触摸开始",e); this.setData({ isScroll:true }); isDelete=false; if(lineTimeId){ clearTimeout(lineTimeId); lineTimeId=''; } }, //歌词触碰结束 touchend(e){ isDelete=true; console.log("触摸结束",e); if(lineTimeId!='')return; lineTimeId=setTimeout(()=>{ if(isDelete===true){ this.setData({ isScroll:false }); lineTimeId=''; } },4000); }, //歌词滚动 scroll(e){ if(this.data.isScroll){ let i=parseInt(e.detail.scrollTop/27); if(!this.data.lrcArr[i])return;//空白区域,没有时间不执行 console.log("滚动",e.detail.scrollTop,this.data.lrcArr[i]);//歌词的间隔区间为27 this.setData({ locationTime:this.data.lrcArr[i], locationShowTime:dayjs(this.data.lrcArr[i]*1000).format("mm:ss") }); } }, //歌词拖动播放 playScroll(e){ console.log("拖动播放",e); let value=this.data.locationTime; bg.seek(value); this.setData({ isScroll:false, isPlay:true }); this.update(); }, //切换是否显示歌词 isLrc(e){ this.setData({ isLrc:!this.data.isLrc }); }, //下载音乐 download(e){ console.log(e); wx.setClipboardData({ data: this.data.musics.url, success:res=>{ console.log(res.data); wx.hideToast(); wx.showToast({ title: '已复制链接', }) } }) }, //进度条拖动 sliderNow(e){ console.log(e); let nowTime=dayjs(e.detail.value*1000).format('mm:ss'); this.setData({ nowTime:nowTime, isSlider:true }); }, //进度条 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); }, //上一首 back(){ let index; if(this.data.categoryActive===0){//顺序播放 index=this.data.index-1; if(index<0){//第一首处理 index=this.data.ids.length-1; } }else if(this.data.categoryActive===1){//随机播放 index=parseInt(Math.random()*this.data.ids.length); }else{//单曲循环 index=this.data.index; bg.stop(); } console.log(index); this.setData({ index:index, isPlay:true }); this.getData();//重新获取音乐 }, //下一首 next(){ let index; if(this.data.categoryActive===0){//顺序播放 index=this.data.index+1; if(index===this.data.ids.length){//最后一首处理 index=0; } }else if(this.data.categoryActive===1){//随机播放 index=parseInt(Math.random()*this.data.ids.length); }else{//单曲循环 index=this.data.index; bg.stop(); } console.log(index); this.setData({ index:index, isPlay:true }); this.getData();//重新获取音乐 }, //播放音乐 playMusic(){ console.log("播放",this.data.musics.url,this.data.songs.name); bg.src=this.data.musics.url; bg.title=this.data.songs.name; //设置进度条 console.log("进度条",bg.duration); }, //切换播放方式 toggleCategory(e){ // console.log(e); let i=this.data.categoryActive+1; if(i>2)i=0; this.setData({ categoryActive:i }); }, //切换播放 togglePlay(e){ console.log(e); this.setData({ isPlay:!this.data.isPlay }); if(this.data.isPlay){ bg.play(); }else{ bg.pause(); } }, //切换收藏 toggleCollect(e){ console.log(e); this.setData({ isCollect:!this.data.isCollect }); }, //获取音乐数据 getData(){ let id=this.data.ids[this.data.index]; console.log(id); //获取歌曲详情 api.songDetail(id).then(res=>{ console.log("歌曲详情:",res); this.setData({ songs:res.songs[0] }); //获取音乐url api.songUrl(id).then(res=>{ console.log("歌曲音乐url:",res); this.setData({ musics:res.data[0] }); this.playMusic();//播放音乐 wx.hideLoading(); }).catch(err=>{ console.log(err); }); }).catch(err=>{ console.log(err); }); //获取歌词 api.lyric(id).then(res=>{ console.log("歌曲歌词 :",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]);//毫秒:+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"),"")); } }); //去空 let a1=[],a2=[]; for(let i=0;i<arr.length;i++){ if(arr[i]&&lrcArr[i]){//当前是否有歌词 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); }); }, //定时器更新 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){//都有数据 //处理歌词当前位置 // let len=0;//歌词排除为空的下标 for(let i=0;i<this.data.lrcArr.length;i++){ if(nowTime>this.data.lrcArr[this.data.lrcArr.length-1]){//最后的歌词 this.setData({ location:this.data.lrcArr.length }); break; } console.log(nowTime,this.data.lrcArr[i]); if(nowTime>=this.data.lrcArr[i]&&nowTime<this.data.lrcArr[i+1]){ console.log("歌词滚动"); this.setData({ location:i }); break; } } //设置滚动 if(this.data.isScroll===false){ if(this.data.locationIndex!=this.data.location){ this.setData({ timeLen:this.data.lrcArr[this.data.location+1]-this.data.lrcArr[this.data.location] }); } this.setData({ locationIndex:this.data.location }); } //处理显示 totalTime=dayjs(totalTime*1000).format('mm:ss'); nowTime=dayjs(nowTime*1000).format('mm:ss'); console.log("时间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(',');//字符串拆分 console.log(ids); this.setData({ index:Number(options.index), ids:ids }); this.getData(); //背景音频 bg.onEnded(()=>{ console.log("播放完毕。"); this.next(); }); bg.onPause(()=>{ console.log("暂停播放"); this.setData({ isPlay:false }); }); bg.onPlay(()=>{ console.log("开始播放"); this.setData({ isPlay:true }); }); bg.onTimeUpdate(()=>{ // console.log("播放进度更新"); // this.update(); }); }, onReady: function () { }, onShow: function () { //设置进度条 timeId=setInterval(()=>{ this.update(); },500); }, onHide: function () { }, onUnload: function () { //销毁定时器 clearInterval(timeId); }, onPullDownRefresh: function () { }, onReachBottom: function () { }, onShareAppMessage: function () { } })
.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 和 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%; } .z{ } @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); } } /*文字过渡*/ .hover { position: absolute; top: 0; left: 0; color: red; overflow: hidden; width: 100%; white-space: nowrap; } @keyframes test { from { width: 0%; } to { width: 100%; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。