123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468 |
- /**************************************************
- * MKOnlinePlayer v2.41
- * 播放器主功能模块
- * 编写:mengkun(https://mkblog.cn)
- * 时间:2018-3-13
- *************************************************/
- // 播放器功能配置
- var mkPlayer = {
- api: "http://music.ytxmgy.com/api.php", // api地址https://www.mqtv.cc/libs/XMusic.api.php 第二个http://music.ytxmgy.com/api.php
- loadcount: 20, // 搜索结果一次加载多少条
- method: "POST", // 数据传输方式(POST/GET)
- defaultlist: 3, // 默认要显示的播放列表编号
- autoplay: true, // 是否自动播放(true/false) *此选项在移动端可能无效
- coverbg: true, // 是否开启封面背景(true/false) *开启后会有些卡
- mcoverbg: true, // 是否开启[移动端]封面背景(true/false)
- dotshine: true, // 是否开启播放进度条的小点闪动效果[不支持IE](true/false) *开启后会有些卡
- mdotshine: false, // 是否开启[移动端]播放进度条的小点闪动效果[不支持IE](true/false)
- volume: 0.6, // 默认音量值(0~1之间)
- version: "v2.41", // 播放器当前版本号(仅供调试)
- debug: false // 是否开启调试模式(true/false)
- };
- /*******************************************************
- * 以下内容是播放器核心文件,不建议进行修改,否则可能导致播放器无法正常使用!
- *
- * 哈哈,吓唬你的!想改就改呗!不过建议修改之前先【备份】,要不然改坏了弄不好了。
- ******************************************************/
- // 存储全局变量
- var rem = [];
- // 音频错误处理函数
- function audioErr() {
- // 没播放过,直接跳过
- if(rem.playlist === undefined) return true;
- if(rem.errCount > 10) { // 连续播放失败的歌曲过多
- layer.msg('似乎出了点问题~播放已停止');
- rem.errCount = 0;
- } else {
- rem.errCount++; // 记录连续播放失败的歌曲数目
- layer.msg('当前歌曲播放失败,自动播放下一首');
- nextMusic(); // 切换下一首歌
- }
- }
- // 点击暂停按钮的事件
- function pause() {
- if(rem.paused === false) { // 之前是播放状态
- rem.audio[0].pause(); // 暂停
- } else {
- // 第一次点播放
- if(rem.playlist === undefined) {
- rem.playlist = rem.dislist;
- musicList[1].item = musicList[rem.playlist].item; // 更新正在播放列表中音乐
- // 正在播放 列表项已发生变更,进行保存
- playerSavedata('playing', musicList[1].item); // 保存正在播放列表
- listClick(0);
- }
- rem.audio[0].play();
- }
- }
- // 循环顺序
- function orderChange() {
- var orderDiv = $(".btn-order");
- orderDiv.removeClass();
- switch(rem.order) {
- case 1: // 单曲循环 -> 列表循环
- orderDiv.addClass("player-btn btn-order btn-order-list");
- orderDiv.attr("title", "列表循环");
- layer.msg("列表循环");
- rem.order = 2;
- break;
- case 3: // 随机播放 -> 单曲循环
- orderDiv.addClass("player-btn btn-order btn-order-single");
- orderDiv.attr("title", "单曲循环");
- layer.msg("单曲循环");
- rem.order = 1;
- break;
- // case 2:
- default: // 列表循环(其它) -> 随机播放
- orderDiv.addClass("player-btn btn-order btn-order-random");
- orderDiv.attr("title", "随机播放");
- layer.msg("随机播放");
- rem.order = 3;
- }
- }
- // 播放
- function audioPlay() {
- rem.paused = false; // 更新状态(未暂停)
- refreshList(); // 刷新状态,显示播放的波浪
- $(".btn-play").addClass("btn-state-paused"); // 恢复暂停
- $(".music-cover").addClass("btn-xz"); // 旋转
- if((mkPlayer.dotshine === true && !rem.isMobile) || (mkPlayer.mdotshine === true && rem.isMobile)) {
- $("#music-progress .mkpgb-dot").addClass("dot-move"); // 小点闪烁效果
- }
- var music = musicList[rem.playlist].item[rem.playid]; // 获取当前播放的歌曲信息
- var msg = " 正在播放: " + music.name + " - " + music.artist; // 改变浏览器标题
- // 清除定时器
- if (rem.titflash !== undefined )
- {
- clearInterval(rem.titflash);
- }
- // 标题滚动
- titleFlash(msg);
- }
- // 标题滚动
- function titleFlash(msg) {
- // 截取字符
- var tit = function() {
- msg = msg.substring(1,msg.length)+ msg.substring(0,1);
- document.title = msg;
- };
- // 设置定时间 300ms滚动
- rem.titflash = setInterval(function(){tit()}, 300);
- }
- // 暂停
- function audioPause() {
- rem.paused = true; // 更新状态(已暂停)
- $(".list-playing").removeClass("list-playing"); // 移除其它的正在播放
- $(".btn-play").removeClass("btn-state-paused"); // 取消暂停
- $(".music-cover").removeClass("btn-xz"); // 旋转
- $("#music-progress .dot-move").removeClass("dot-move"); // 小点闪烁效果
- // 清除定时器
- if (rem.titflash !== undefined )
- {
- clearInterval(rem.titflash);
- }
- document.title = rem.webTitle; // 改变浏览器标题
- }
- // 播放上一首歌
- function prevMusic() {
- playList(rem.playid - 1);
- }
- // 播放下一首歌
- function nextMusic() {
- switch (rem.order ? rem.order : 1) {
- case 1,2:
- playList(rem.playid + 1);
- break;
- case 3:
- if (musicList[1] && musicList[1].item.length) {
- var id = parseInt(Math.random() * musicList[1].item.length);
- playList(id);
- }
- break;
- default:
- playList(rem.playid + 1);
- break;
- }
- }
- // 自动播放时的下一首歌
- function autoNextMusic() {
- if(rem.order && rem.order === 1) {
- playList(rem.playid);
- } else {
- nextMusic();
- }
- }
- // 歌曲时间变动回调函数
- function updateProgress(){
- // 暂停状态不管
- if(rem.paused !== false) return true;
- // 同步进度条
- music_bar.goto(rem.audio[0].currentTime / rem.audio[0].duration);
- // 同步歌词显示
- scrollLyric(rem.audio[0].currentTime);
- }
- // 显示的列表中的某一项点击后的处理函数
- // 参数:歌曲在列表中的编号
- function listClick(no) {
- // 记录要播放的歌曲的id
- var tmpid = no;
- // 调试信息输出
- if(mkPlayer.debug) {
- console.log("点播了列表中的第 " + (no + 1) + " 首歌 " + musicList[rem.dislist].item[no].name);
- }
- // 搜索列表的歌曲要额外处理
- if(rem.dislist === 0) {
- // 没播放过
- if(rem.playlist === undefined) {
- rem.playlist = 1; // 设置播放列表为 正在播放 列表
- rem.playid = musicList[1].item.length - 1; // 临时设置正在播放的曲目为 正在播放 列表的最后一首
- }
- // 获取选定歌曲的信息
- var tmpMusic = musicList[0].item[no];
- // 查找当前的播放列表中是否已经存在这首歌
- for(var i=0; i<musicList[1].item.length; i++) {
- if(musicList[1].item[i].id == tmpMusic.id && musicList[1].item[i].source == tmpMusic.source) {
- tmpid = i;
- playList(tmpid); // 找到了直接播放
- return true; // 退出函数
- }
- }
- // 将点击的这项追加到正在播放的条目的下方
- musicList[1].item.splice(rem.playid + 1, 0, tmpMusic);
- tmpid = rem.playid + 1;
- // 正在播放 列表项已发生变更,进行保存
- playerSavedata('playing', musicList[1].item); // 保存正在播放列表
- } else { // 普通列表
- // 与之前不是同一个列表了(在播放别的列表的歌曲)或者是首次播放
- if((rem.dislist !== rem.playlist && rem.dislist !== 1) || rem.playlist === undefined) {
- rem.playlist = rem.dislist; // 记录正在播放的列表
- musicList[1].item = musicList[rem.playlist].item; // 更新正在播放列表中音乐
- // 正在播放 列表项已发生变更,进行保存
- playerSavedata('playing', musicList[1].item); // 保存正在播放列表
- // 刷新正在播放的列表的动画
- refreshSheet(); // 更改正在播放的列表的显示
- }
- }
- playList(tmpid);
- return true;
- }
- // 播放正在播放列表中的歌曲
- // 参数:歌曲在列表中的ID
- function playList(id) {
- // 第一次播放
- if(rem.playlist === undefined) {
- pause();
- return true;
- }
- // 没有歌曲,跳出
- if(musicList[1].item.length <= 0) return true;
- // ID 范围限定
- if(id >= musicList[1].item.length) id = 0;
- if(id < 0) id = musicList[1].item.length - 1;
- // 记录正在播放的歌曲在正在播放列表中的 id
- rem.playid = id;
- // 如果链接为空,则 ajax 获取数据后再播放
- if(musicList[1].item[id].url === null || musicList[1].item[id].url === "") {
- ajaxUrl(musicList[1].item[id], play);
- } else {
- play(musicList[1].item[id]);
- }
- }
- // 初始化 Audio
- function initAudio() {
- rem.audio = $('<audio></audio>').appendTo('body');
- // 应用初始音量
- rem.audio[0].volume = volume_bar.percent;
- // 绑定歌曲进度变化事件
- rem.audio[0].addEventListener('timeupdate', updateProgress); // 更新进度
- rem.audio[0].addEventListener('play', audioPlay); // 开始播放了
- rem.audio[0].addEventListener('pause', audioPause); // 暂停
- $(rem.audio[0]).on('ended', autoNextMusic); // 播放结束
- rem.audio[0].addEventListener('error', audioErr); // 播放器错误处理
- }
- // 播放音乐
- // 参数:要播放的音乐数组
- function play(music) {
- // 调试信息输出
- if(mkPlayer.debug) {
- console.log('开始播放 - ' + music.name);
- console.info('id: "' + music.id + '",\n' +
- 'name: "' + music.name + '",\n' +
- 'artist: "' + music.artist + '",\n' +
- 'album: "' + music.album + '",\n' +
- 'source: "' + music.source + '",\n' +
- 'url_id: "' + music.url_id + '",\n' +
- 'pic_id: "' + music.pic_id + '",\n' +
- 'lyric_id: "' + music.lyric_id + '",\n' +
- 'pic: "' + music.pic + '",\n' +
- 'url: "' + music.url + '"');
- }
- // 遇到错误播放下一首歌
- if(music.url == "err") {
- audioErr(); // 调用错误处理函数
- return false;
- }
- addHis(music); // 添加到播放历史
- // 如果当前主界面显示的是播放历史,那么还需要刷新列表显示
- if(rem.dislist == 2 && rem.playlist !== 2) {
- loadList(2);
- } else {
- refreshList(); // 更新列表显示
- }
- try {
- rem.audio[0].pause();
- rem.audio.attr('src', music.url);
- rem.audio[0].play();
- } catch(e) {
- audioErr(); // 调用错误处理函数
- return;
- }
- rem.errCount = 0; // 连续播放失败的歌曲数归零
- music_bar.goto(0); // 进度条强制归零
- changeCover(music); // 更新封面展示
- ajaxLyric(music, lyricCallback); // ajax加载歌词
- music_bar.lock(false); // 取消进度条锁定
- }
- // 我的要求并不高,保留这一句版权信息可好?
- // 保留了,你不会损失什么;而保留版权,是对作者最大的尊重。
- console.info('欢迎使用 MKOnlinePlayer!\n当前版本:'+mkPlayer.version+' \n作者:mengkun(https://mkblog.cn)\n歌曲来源于各大音乐平台\nGithub:https://github.com/mengkunsoft/MKOnlineMusicPlayer');
- // 音乐进度条拖动回调函数
- function mBcallback(newVal) {
- var newTime = rem.audio[0].duration * newVal;
- // 应用新的进度
- rem.audio[0].currentTime = newTime;
- refreshLyric(newTime); // 强制滚动歌词到当前进度
- }
- // 音量条变动回调函数
- // 参数:新的值
- function vBcallback(newVal) {
- if(rem.audio[0] !== undefined) { // 音频对象已加载则立即改变音量
- rem.audio[0].volume = newVal;
- }
- if($(".btn-quiet").is('.btn-state-quiet')) {
- $(".btn-quiet").removeClass("btn-state-quiet"); // 取消静音
- }
- if(newVal === 0) $(".btn-quiet").addClass("btn-state-quiet");
- playerSavedata('volume', newVal); // 存储音量信息
- }
- // 下面是进度条处理
- var initProgress = function(){
- // 初始化播放进度条
- music_bar = new mkpgb("#music-progress", 0, mBcallback);
- music_bar.lock(true); // 未播放时锁定不让拖动
- // 初始化音量设定
- var tmp_vol = playerReaddata('volume');
- tmp_vol = (tmp_vol != null)? tmp_vol: (rem.isMobile? 1: mkPlayer.volume);
- if(tmp_vol < 0) tmp_vol = 0; // 范围限定
- if(tmp_vol > 1) tmp_vol = 1;
- if(tmp_vol == 0) $(".btn-quiet").addClass("btn-state-quiet"); // 添加静音样式
- volume_bar = new mkpgb("#volume-progress", tmp_vol, vBcallback);
- };
- // mk进度条插件
- // 进度条框 id,初始量,回调函数
- mkpgb = function(bar, percent, callback){
- this.bar = bar;
- this.percent = percent;
- this.callback = callback;
- this.locked = false;
- this.init();
- };
- mkpgb.prototype = {
- // 进度条初始化
- init : function(){
- var mk = this,mdown = false;
- // 加载进度条html元素
- $(mk.bar).html('<div class="mkpgb-bar"></div><div class="mkpgb-cur"></div><div class="mkpgb-dot"></div>');
- // 获取偏移量
- mk.minLength = $(mk.bar).offset().left;
- mk.maxLength = $(mk.bar).width() + mk.minLength;
- // 窗口大小改变偏移量重置
- $(window).resize(function(){
- mk.minLength = $(mk.bar).offset().left;
- mk.maxLength = $(mk.bar).width() + mk.minLength;
- });
- // 监听小点的鼠标按下事件
- $(mk.bar + " .mkpgb-dot").mousedown(function(e){
- e.preventDefault(); // 取消原有事件的默认动作
- });
- // 监听进度条整体的鼠标按下事件
- $(mk.bar).mousedown(function(e){
- if(!mk.locked) mdown = true;
- barMove(e);
- });
- // 监听鼠标移动事件,用于拖动
- $("html").mousemove(function(e){
- barMove(e);
- });
- // 监听鼠标弹起事件,用于释放拖动
- $("html").mouseup(function(e){
- mdown = false;
- });
- function barMove(e) {
- if(!mdown) return;
- var percent = 0;
- if(e.clientX < mk.minLength){
- percent = 0;
- }else if(e.clientX > mk.maxLength){
- percent = 1;
- }else{
- percent = (e.clientX - mk.minLength) / (mk.maxLength - mk.minLength);
- }
- mk.callback(percent);
- mk.goto(percent);
- return true;
- }
- mk.goto(mk.percent);
- return true;
- },
- // 跳转至某处
- goto : function(percent) {
- if(percent > 1) percent = 1;
- if(percent < 0) percent = 0;
- this.percent = percent;
- $(this.bar + " .mkpgb-dot").css("left", (percent*100) +"%");
- $(this.bar + " .mkpgb-cur").css("width", (percent*100)+"%");
- return true;
- },
- // 锁定进度条
- lock : function(islock) {
- if(islock) {
- this.locked = true;
- $(this.bar).addClass("mkpgb-locked");
- } else {
- this.locked = false;
- $(this.bar).removeClass("mkpgb-locked");
- }
- return true;
- }
- };
|