啊哈哈哈,代码镇楼。太菜了,让我写的这个代码一点可读性都没了……
不过还好,效果达到了,先放了渲染图。
今天增加了三个主要功能,1音量控制,2上传文件,3切歌。
第一点,音量控制没什么好说的,和昨天的进度条一样,改一下大小,定位,增加一个点击事件。
<
这是音量控制的HTML代码,我的点击事件是绑定在父元素volumBackground上面的,这会导致一个问题,就是那个Icon也会获得这个事件,所以就会导致一个Bug——连续点击右边时候,音量会来回调,因为我是用offsetX方法来计算,所以音量在考进最右边的时候,事件的当事方算在了Icon上面,所以就导致offsetX大小的跳跃,本想着搜一圈阻止事件捕获的的方法,最后我发现,只要我把event.target加上一个判断就可以了,如果事件不是发生在Icon上面,我再调整音量。
昨天没发现其实进度条也有这个Bug,不过现在加上这个if判断就好了。
重头戏上传文件来了。我之前对文件一窍不通,用什么方法都母鸡,搜了一下MDN,
var
这是MDN文档上的描述,其实我到现在都没看完,也每咋看懂,我就先照着上面的例子,拿过来用了……
var secondToMin = function(seconds) {
var m = parseInt(seconds / 60)
var s = parseInt(seconds % 60)
return m + ':' + s
}
var songSrcList = []
var songImageList = []
var fileRead = function() {
var inputElement = document.querySelector('#fileread')
inputElement.addEventListener('change', function(event) {
var file = event.target.files[0]
songSrcList.push(file.name)
e('#musicplay').src = file.name
jsmediatags.read(file, {
onSuccess: function(tag) {
var songImageData = tag['tags']['picture']['data']
var songImage = 'data:image/png;base64,' + arrayBufferToBase64(songImageData)
e('.songImageAll').src = songImage
songImageList.push(songImage)
var artist = tag['tags']['artist']
var songName = tag['tags']['TIT2']['data']
var songListHtml = `
<li>
<a href="#" class="${songName}${artist}">
<div id="${songName}">
<audio class="${songName}"src="${file.name}"></audio>
<span class="songName">${songName}</span>
<span class="artist">${artist}</span>
</div>
</a>
</li>
`
e('ul').insertAdjacentHTML('beforeend', songListHtml)
var url = URL.createObjectURL(file)
var audioElement = new Audio(url);
var duration
audioElement.addEventListener("loadedmetadata", function (_event) {
duration = audioElement.duration;
var songTime = secondToMin(duration)
var songTimeHtml = `
<span class="songTime">${songTime}</span>
`
e('#' + songName).insertAdjacentHTML('beforeend', songTimeHtml)
})
},
onError: function(error) {
log('error:', error)
}
})
}, false)
}
这么一长串就是文章开头的那张图,简直没有可读性了……不管,等我把功能写完了,我再来封装。
首先是上传文件,把当前audio标签的src改成上传的,然后通过我们第一篇文章中说的方法——jsmediatags.read来获取mp3文件的ID3信息,你也别问我怎么获取的,我也不懂,按照人家的方式来就能获取。获取了歌曲的封面Image将他push进一个array中,这是我做切歌功能的时候想到了,后来才加上去的。我们拿到MP3的songName、artist将这些信息,加到模板字符串中,再把模版字符串添加到页面中。
MP3中的ID3信息是不包含总时长信息的,至少我没发现有这个数据,查了一下也没有结果,所以我要拿到歌曲的时长,就只能通过duration方法,不过这里有个坑,如果我直接再添加html之后选择audio标签,调用duration方法的话,就会报错,NaN。搜了一下原因,说是audio标签是异步添加。我也搞不懂啊,我就是想拿到这个时长信息而已……搜了一下发现简书上面有一篇文章讲过这个问题,不过代码我其实不太看得懂,不过我复制过来跑了一下,确实能得到总时间,Great。by the way 我发现简书的代码模块好漂亮,特别语法高亮比其他家的高了好几个等级啊。
拿到了歌曲时长后,再用模板字符串添加到页面中。至此上传文件就写完了。
切歌,这个功能我想很简单,因为我写过轮播图,切换按钮我还记得。不直接帖代码了,用图吧,知乎的代码块功能真是不行啊……
首先是分别算出下一首和上一首的index。又是一道坑啊,我原来想的是,直接那现在的 .src 和songSrcList中的比较,再求出index,我也确实这么做了……
不过这样拿不到index,原因是当前的 .src 是一个path,系统加上了一些路径信息。我把当前的 .src log出来,发用 .split('/') 切成list,再取第6 个就是我当前文件夹下的 src信息,如果包含中文的话,还需要用decodeURI来解码,这样就拿到了src信息。于是切歌这个功能,初步做好了。
不过只是这样的话,有几个问题,首先 旋转图片不会切换, 如果是正在播放时切歌,它不会自动播放。
先解决图片问题,这时候我就去上面把,读到的ID3信息中的image数据push到一个array中,这个image的array和songSrcList中的下标是一致的,所以我再切换一下当前图片的src就可以了,毕竟index已经算出来了。剩下一个自动播放也好办,正在播放的时候切歌的话,我昨天写的controls函数中的 .suspend元素的classlist中 是包含playing这个class的,所以再加一个判断,如果包含playing这个class,就播放。
至此音乐播放器的大部分功能都做完了,还剩下一个点击歌曲列表切歌功能没有做。明天再说吧,先睡了。最后放一下播放器的视频。不过声音是我用一种便宜的做法录制的——我电脑上有声卡和麦克风,qt录屏录不到系统声音,我也懒得装软件就直接录耳机的声音了,将就一下吧。