一、滚动歌词改变当前歌曲进度的冲突
当音乐在播放时进行歌词拖动事件,那么两个事件会同时发生,引起冲突,造成拖动歌词不流畅,和当滚动条滚到底部最大值时,用户再去自行往下拖动歌词会失去选中歌词的效果,并且歌曲进度条会跳回至开头附近的问题;
目前的解决办法:
将两个事件分开绑定,但仍有不足:
// 歌词界面滑动事件
// 用scroll事件会造成在歌词界面时播放歌曲卡顿,瞬间跳转到某一时间点
// 但是用touchmove事件又会造成歌词在滑动松手后不会一直居中,但是二者结合就比较完美
let scrollTimeout = null;
$(".onlyLyrics").on("scroll", function () {
for (let z of $(".onlyLyrics p")) {
// 不设置这个判断会造成切换到歌词界面时会跳回卡在滚动条卷去最大值的地方的那句歌词
if (($(".onlyLyrics").scrollTop() >= $(".onlyLyrics")[0].scrollHeight - $(".onlyLyrics").height()) == false) {
let stamp = $(".onlyLyrics").scrollTop() + ($(".onlyLyrics").height() / 2)
if (z.offsetTop - stamp <= 10) {
$(z).siblings().removeClass("chooseLyric")
$(z).addClass("chooseLyric")
$(".onlyLyrics").on("touchmove", function () {
progress.value = backStepping(z)
audio.currentTime = Number(progress.value) / 1000
updateProgress()
})
}
}
}
})
不足之处:
当用户松开手后,歌词仍然会滑动(这是正常的),但是不会再根据滑动停止后最后居中的歌词改变音频进度,音频进度会停留在松手时选中的歌词处。
二、最后一句歌词无法滚动到居中位置
原因:滚动条已经达到最大值,无法再向下滚动。
解决方法:我选择给最后一句歌词加一个底部外边距,因为如果给整个盒子加内边距的话还要改判断歌词的计算方法。
p:last-child {
margin-bottom: calc(35vh - 50px);
}
或许也会引发新的BUG,有待发掘。
三、修改进度条默认样式
没有学过这个属性,以下代码来自网络:
/*横条样式*/
input[type=range] {
/*清除系统默认样式*/
-webkit-appearance: none;
/*设置左边颜色为#fa3f1e,右边颜色为#ddd*/
background: -webkit-linear-gradient(#fa3f1e, #fa3f1e) no-repeat, #ddd;
/*设置已滑过的比例*/
background-size: 0%;
/*横条的高度*/
height: 5px;
border-radius: 5px;
}
/*拖动块的样式*/
input[type=range]::-webkit-slider-thumb {
/*清除系统默认样式*/
-webkit-appearance: none;
/*拖动块高度*/
height: 10px;
/*拖动块宽度*/
width: 10px;
/*拖动块背景*/
background: rgb(196, 195, 195);
/*外观设置为圆形*/
border-radius: 50%;
}
四、进度条监听事件
同上,没有学过这个事件,善用搜索引擎:
// 进度条滑动监听事件
$(".progress").on('input propertychange', function () {
audio.currentTime = Number(progress.value) / 1000
updateProgress()
// 改变歌词界面的歌词
for (let y of $(".onlyLyrics p")) {
let dValue = Number(progress.value) - backStepping(y)
if (dValue > 0 && dValue <= 3000) {
$(y).siblings().removeClass("chooseLyric")
$(y).addClass("chooseLyric")
if (y.offsetTop > $(y).parent().height() / 2) {
let offsetScroll = y.offsetTop - $(y).parent().height() / 2
$(y).parent().scrollTop(offsetScroll)
break
}
}
}
// 改变唱片界面的歌词
for (let x of everyLyric) {
let dValue = Number(progress.value) - backStepping(x)
if (dValue > 0 && dValue <= 3000) {
$(".lyric").text(x.lyr)
break
} else if (dValue < 0) {
break
}
}
})
五、渲染榜单乱序
异步问题,经过同桌大哥的指点悟了这个比较好的思路:
把请求回来的数据先存到一个数组里,再遍历数组去渲染html,就不会产生异步,榜单顺序就是正确的了
// 获取到榜单歌曲id后进行请求
let rankingListArr = []
res.privileges.forEach(function (element, index) {
$.get(baseUrl + `/song/detail?ids=${element.id}`, function (res) {
rankingListArr[index] = {
"musicId": res.songs[0].id,
"index": index,
"name": res.songs[0].name,
"artists": artists(res.songs[0].ar)
}
$("#rankingList").empty()
rankingListArr.forEach(function (value, index) {
$("#rankingList").append(`<li musicId="${value.musicId}">
<div class="nums ${index <= 2 ? 'topThree' : ""}">
${(index + 1).toString().padStart(2, "0")}</div>
<div class="musicInfo">
<div>
<p>${value.name}</p>
<p>${value.artists}</p>
</div>
<div class="play">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-bofang"></use>
</svg>
</div>
</div>
</li>`)
})
setMusicList(index, res)
})
});