大佬教程收集整理的这篇文章主要介绍了HTML5移动端音乐播放器(启蒙篇),大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
这段时间公司一直在做一个PC的教育类单页应用,庞大复杂,涉及非常多H5的知识,音频就是其中的一部分。前些天偷台风的闲暇时写了一个移动端音乐播放器,作为练手项目。
注意:使用PC浏览最好打开移动设备模式,使用移动设备浏览需要关闭无痕浏览模式(否则无法使用本地存储,一般浏览器都是默认不开启),项目需要在本地服务器或线上服务器运行,以file:///形式的地址打开是无法进行ajax请求的,从而无法看到音乐数据。
播放器的基础操作,上一首,下一首(顺序播放、随机播放、单曲循环),播放暂停,滑动时间轴的歌词定位
初始handlebar模板渲染音乐列表数据,下拉滚动加载音乐列表数据。
歌曲列表可添加喜爱音乐,于下次刷新时更新喜爱音乐列表,基于HTML5本地存储。
布局采用rem布局,自适应移动端手机设备。
iconfont在线图标应用的使用
css:存放样式文件
lib: 存放公共脚本库
js: 存放项目脚本文件
img: 存放图片
fonts: 项目字体文件
res: 项目音乐资源
ui:项目ui文件(psd)
// ============================配置变量================================ var rootPath = window.LOCATIOn.href.replace(/\/\w+\.\w+/,"/"); var SetTings = { playmode: 0,//0列表循环,1随机,2为单曲循环 volume: 0.5,//音量 initNum: 10,//列表初始化歌曲数 reqNum: 10 //后续请求歌曲数 }; // ============================工具函数================================ var Util = (function() { return { } })() // ============================Dom选择器================================ var Dom = { } // ============================全局变量================================ var winH = $(window).height(); var songNum = 0; //当前列表歌曲数目 var lrcHighIndex = 0; // 歌词高亮索引 var lrcMoveIndex = 0; // 歌词移动单位索引 var moveDis = 0; // 单句歌词每次移动距离 var duration = 0; // 当前歌曲的时间 var index = 0; //当前播放歌曲的索引 var songInfo = null; // 当前歌曲信息 var songModelUI = null; // 当前歌曲UI模型 var timeArr = []; //当前歌曲时间数组 var formatTimeArr = []; //当前歌曲时间数组(格式化为秒数) // ============================入口函数================================ function main() { initUIFrame(); var initModel = PlayerModel(); var songListuI = ModelUIFrame(Dom.songListContainer); var lsongListuI = ModelUIFrame(Dom.lSongListContainer); initModel.getSongList("data/data.json",function(data) { // 生成所有歌曲列表 songListuI.renderList(data,null,function() { songListuI.updateList(); }); // 生成喜爱歌曲列表 initModel.getLoveSongArr(function(lSongArr) { lsongListuI.renderList(data,1,lSongArr); }); // 添加动画 Util.addAnimationDelay(Dom.song); // 保存歌词数据 initModel.saveLyric(data); }); EventHandler(); } // ============================初始化UI函数================================ function initUIFrame() { } // ============================实现数据交互方法================================ function PlayerModel() { } // ============================模型动态UI模块================================ function ModelUIFrame(container) { } // ============================事件绑定模块================================ function EventHandler() { } // @L_874_26@入口函数 main();
使用前端模板优点是把数据和结构分离出来,代码更清晰。但后来发现handlerbar.js似乎无法在js中示例模板对象,而Html中的handlebar在初次进入页面便会被编译了,因此后续添加音乐还是采用传统的拼接字符串的方式,如果你有更优雅的动态加载方式,欢迎讨论交流。
html:handlebars模板包含在script标签之中并且type类型为”text/x-handlebars-template”,在初始化页面的时候根据js获取数据植入后就渲染出相应的html。
<script id="sListTpl" type="text/x-handlebars-template"> {{#each this}} {{#isInitData this @index}} <li class="song btm-line" data-src={{songSrc}} data-index={{iD}}> <div class="poster"> <img src={{poster.thumbnail}}> </div> <div class="songinfo"> <h2 class="lsongname">{{songNamE}}</h2> <sub class="lsinger">{{singer}}</sub> </div> <div class="loveflag"> <i class="icon icon-love {{#if loveFlag}}active{{/if}}"></i> </div> </li> {{/isInitData}} {{/each}} </script>
js:
function renderAllList(data) { var preTpl; var lsongArr = Util.getItem('lsonglist') === null ? [] : JSON.parse(Util.getItem('lsonglist')); // 生成列表 if (!sListTpl) { // 后续动态生成歌曲 var tpl = ""; var songIndex = songNum; $.each(data,function(index,el) { if (index >= songIndex && index < songIndex + SetTings.reqNum) { tpl += "<li class='song btm-line' data-src='res/music/" + songNum + ".mp3' data-index='" + songNum + "'><div class='poster'>[站外图片上传中……(1)]</div><div class='songinfo'><h2 class='lsongname'>" + el.songName + "</h2><sub class='lsinger'>" + el.singer + "</sub></div><div class='loveflag'><i class='icon icon-love '></i></div></li>"; songNum++; } }); $(container).append($(tpl)); } else { // 首次生成歌曲 preTpl = Handlebars.compile(sListTpl); $(container).html(preTpl(data)); } // 更新喜爱图标 if (lsongArr.length !== 0) { $.each(lsongArr,val) { Dom.songListContainer.find(".song").eq(val).find(".icon-love").addClass('active'); }); } }
大体上指的是html根元素上定义一个字体大小,然后css样式定义时使用rem作为单位,@L_441_46@margin、paddding、用于绝对定位的单位等等。然后js根据手机设备的屏幕大小,改变根字体的大小,这样整个页面也会跟着相应的缩小或放大。
更多详解,请看这一篇文章《移动端自适应布局解决方案——rem》,您可以猛击这里跳转。
目前音乐播放器的歌词同步显示大概有两种,一种是精确到单个文字,一种是精确到单行歌词。本文实现的是第二种。
页面初始化时,请求歌曲数据json(本地json文件模拟),其中歌名、歌手、图片等按需渲染到html中,将歌词存储到localStorage中。此时,F12打开chrome调试器,进入Application-LocalStorage可以看到:
点击一首歌进入播放页面后,歌词就会从本地存储中读取,此时你会看到生成这样的歌词结构:
每一行歌词都将要将歌词时间绑定在data-point上,监听歌曲播放的timeupdate事件,当歌曲的时间(经过取整处理)与当前data-point值相等时,就为当前歌词高亮(相当于给p添加current类名),并且根据当前高亮歌词的index索引将整个歌词盒子向上移动p标签的高度+margin-top的高度。
来自网易云音乐的歌词数据:
[00:14.64]如果不是那镜子\n[00:16.73]不像你不藏秘密\n[00:21.26]我还不肯相信\n[00:23.02]没有你我的笑更美丽\n[00:28.99]那天听你在电话里略带抱歉的关心\n [00:16.959]摘一颗苹果\n[00:19.800]等你从门前经过\n[00:22.700]送到你的手中帮你解渴\n[00:25.570]像夏天的可乐\n [00:00.00] 作曲 : 周杰伦\n[00:01.00] 作词 : 周杰伦\n[00:05.620]\n[00:37.980]亲吻你的手\n
可以看到格式 = [时间点] + 要显示的文字 + \n
这里有两个坑需要注意:
有的歌词秒数是精确到小数点后两位,有的是三位。
有的歌词(周杰伦《算什么男人》)格式是[时间点]+\n
首先以n将歌词字符串分割成以[时间点]文字的数组,但由于这样分割之后最后一个元素是空的,所以用tempArr.splice(-1,1)删除最后一个元素。
接下来循环遍历这个临时数组,由于上面提到的秒数精确度的问题,所以判断一下index为9是否为数字,若为数字则将该位数字删除。(采用字符串截取方式,若你对js字符串方法不熟悉,可以猛击这里)
经过这样的处理之后,临时数组的元素格式不再有区别了,此时再进行字符串截取,将截取到的时间点放入timeArr,将截取的歌词放入lyricArr,并以返回保存着这两个变量的对象。
function createArrMap(lyriC) { var timeArr = [],lyricArr = []; var tempArr = lyric.split("\n"); tempArr.splice(-1,1); var tempStr = ""; $(tempArr).each(function(indeX) { tempStr = this; if (tempStr.charAt(9).match(/\d/) !== null) { tempStr = tempStr.subString(0,9) + tempStr.subString(10); } timeArr.push(tempStr.subString(0,10)); lyricArr.push(tempStr.subString(10)); }); return { timeArr: timeArr,lyricArr: lyricArr }; }
由于上面歌词格式造成时间点对应的歌词为空,此时如果渲染出一个
标签的高度将为0,这会影响歌词向上移动距离的不统一。因此下面作出个判断如果为空,则替换为“————–”。(为空的时候大多数是歌曲中间停顿或过渡的时候)
function renderLyric(songinfo) { var arrMap = Util.createArrMap(songinfo.lyric); var tpl = ""; $.each(arrMap.lyricArr,lyriC) { var lyricContent = lyric === "" ? "--------------" : lyric; tpl += "<p class='' data-point='" + arrMap.timeArr[index] + "'>" + lyricContent + "</p>"; }); Dom.lrcwrap.html(tpl); }
歌词同步我写在了syncLyric方法中,监听audio元素的timeupdate事件@L_874_26@。
这个方法接收两个参数,第一个是当前播放歌曲时间(秒),第二个是转化为秒数的时间点数组。
如果当前时间>=时间点,那么高亮当前歌词(以lrcHighIndex)存储,并且lrcHighIndex自增1。
当歌词高亮索引lrcHighIndex>=1即歌词高亮不为第一句时,计算索引并让歌词盒子向上移动。
function syncLyric(curs,formatTimeArr) { if (Math.floor(curs) >= formatTimeArr[lrcHighIndex]) { Dom.lrc.eq(lrcHighIndeX).addClass('current').siblings().removeClass('current'); if (lrcHighIndex >= 1) { lrcMoveIndex = lrcHighIndex - 2; moveDis += Util.getMoveDis(lrcMoveIndeX); Dom.lrcwrap.animate({ "top": "-" + moveDis + "px" },100); lrcMoveIndex++; } lrcHighIndex++; } }
以上是大佬教程为你收集整理的HTML5移动端音乐播放器(启蒙篇)全部内容,希望文章能够帮你解决HTML5移动端音乐播放器(启蒙篇)所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。