diff --git a/README.MD b/README.MD index 89b039b..35bde38 100644 --- a/README.MD +++ b/README.MD @@ -1,4 +1,4 @@ -MKOnlineMusicPlayer v2.3 +MKOnlineMusicPlayer v2.31 ======== MKOnlineMusicPlayer 是一款开源的基于 `Meting` 的在线音乐播放器。具有音乐搜索、播放、下载、歌词同步显示、个人网易云音乐播放列表同步等功能。 @@ -41,6 +41,7 @@ php 5.4+, curl_exec, file_get_contents, json_decode, openssl_encrypt ### 待解决的问题 ----- - 高音质音乐下载功能 +- IOS 歌曲播放问题 - 歌曲播放模式切换(单曲循环、随机播放、列表循环)功能 ### 打赏 @@ -52,6 +53,13 @@ php 5.4+, curl_exec, file_get_contents, json_decode, openssl_encrypt ### 更新日志 ----- +#### v2.31 `2017/9/13` +- 优化下载功能,支持直接弹出下载 +- 下载或分享无版权音乐时给出提示 +- 再次降低移动端背景特效内存占用 +- 修复某些手机浏览器列表页右侧菜单按钮下移 BUG +- 升级 Meting 至最新版本 + #### v2.3 `2017/9/9` - 全面支持网易云、QQ、虾米、酷狗、百度音乐源切换 - 移动端歌曲列表支持直接分享、下载歌曲 diff --git a/css/small.css b/css/small.css index 772fb78..a73d05e 100644 --- a/css/small.css +++ b/css/small.css @@ -1,9 +1,9 @@ @charset "utf-8"; /************************************************** - * MKOnlinePlayer v2.2 + * MKOnlinePlayer v2.31 * 小屏幕样式修复 * 编写:mengkun(http://mkblog.cn) - * 时间:2017-3-26 + * 时间:2017-9-13 *************************************************/ /* 小于 900px 采用这个样式 */ @@ -92,7 +92,11 @@ background-position: -30px -365px; right: 0; top: 50%; - transform: translateY(-50%); + -webkit-transform: translateY(-50%); + -moz-transform: translateY(-50%); + -ms-transform: translateY(-50%); + -o-transform: translateY(-50%); + transform: translateY(-50%); z-index: 2; cursor: pointer; } diff --git a/index.html b/index.html index fd1be39..048250f 100644 --- a/index.html +++ b/index.html @@ -4,6 +4,8 @@ + + @@ -141,7 +143,10 @@ - + + + + \ No newline at end of file diff --git a/js/ajax.js b/js/ajax.js index a2c02d9..248987e 100644 --- a/js/ajax.js +++ b/js/ajax.js @@ -1,8 +1,8 @@ /************************************************** - * MKOnlinePlayer v2.2 + * MKOnlinePlayer v2.31 * Ajax 后台数据交互请求模块 * 编写:mengkun(http://mkblog.cn) - * 时间:2017-3-26 + * 时间:2017-9-13 *************************************************/ // ajax加载搜索结果 diff --git a/js/functions.js b/js/functions.js index df4b6e9..8dc1feb 100644 --- a/js/functions.js +++ b/js/functions.js @@ -1,8 +1,8 @@ /************************************************** - * MKOnlinePlayer v2.2 + * MKOnlinePlayer v2.31 * 封装函数及UI交互模块 * 编写:mengkun(http://mkblog.cn) - * 时间:2017-3-26 + * 时间:2017-9-12 *************************************************/ // 判断是否是移动设备 var isMobile = { @@ -370,19 +370,50 @@ function thisShare(obj) { // 下载歌曲 // 参数:包含歌曲信息的数组 function download(music) { - $('1').appendTo('body').click(); - $('#tmp-down').click(); - $('#tmp-down').remove(); // 移除 - window.open(music.url); + if(music.url == 'err' || music.url == "" || music.url == null) { + layer.msg('这首歌不支持下载'); + return; + } + openDownloadDialog(music.url, music.name + ' - ' + music.artist); +} + +/** + * 通用的打开下载对话框方法,没有测试过具体兼容性 + * @param url 下载地址,也可以是一个blob对象,必选 + * @param saveName 保存文件名,可选 + * http://www.cnblogs.com/liuxianan/p/js-download.html + */ +function openDownloadDialog(url, saveName) +{ + if(typeof url == 'object' && url instanceof Blob) + { + url = URL.createObjectURL(url); // 创建blob地址 + } + var aLink = document.createElement('a'); + aLink.href = url; + aLink.download = saveName || ''; // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效 + var event; + if(window.MouseEvent) event = new MouseEvent('click'); + else + { + event = document.createEvent('MouseEvents'); + event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + } + aLink.dispatchEvent(event); } // 获取外链的ajax回调函数 // 参数:包含音乐信息的数组 function ajaxShare(music) { + if(music.url == 'err' || music.url == "" || music.url == null) { + layer.msg('这首歌不支持外链获取'); + return; + } + var tmpHtml = '

' + music.artist + ' - ' + music.name + ' 的外链地址为:

' + ''; - if(music.source != "netease" && music.source != "xiami") { + if(music.source != "netease") { tmpHtml += '

* 当前音乐源歌曲链接有效期较短,不建议作外链使用

' } @@ -410,14 +441,18 @@ function changeCover(music) { $(".sheet-item[data-no='1'] .sheet-cover").attr('src', img); // 改变正在播放列表的图像 if(img == "err") img = ""; // 背景为空 - if((mkPlayer.coverbg === true && !rem.isMobile) || (mkPlayer.mcoverbg === true && rem.isMobile)) { // 开启了封面背景 + + if(mkPlayer.mcoverbg === true && rem.isMobile && img) // 移动端封面 + { + $("#music-cover").load(function(){ + $("#mobile-blur").css('background-image', 'url("' + img + '")'); + }); + } + else if(mkPlayer.coverbg === true && !rem.isMobile) // PC端封面 + { $("#music-cover").load(function(){ if(animate) { // 渐变动画也已完成 - if(rem.isMobile) { // 移动端禁用动画,节约内存 - $("#mobile-blur").css('background-image', 'url("' + img + '")'); - } else { - $("#blur-img").backgroundBlur(img); // 替换图像并淡出 - } + $("#blur-img").backgroundBlur(img); // 替换图像并淡出 $("#blur-img").animate({opacity:"1"}, 2000); // 背景更换特效 } else { imgload = true; // 告诉下面的函数,图片已准备好 @@ -428,12 +463,7 @@ function changeCover(music) { // 渐变动画 $("#blur-img").animate({opacity: "0.2"}, 1000, function(){ if(imgload) { // 如果图片已经加载好了 - if(rem.isMobile) { - $("#mobile-blur").css('background-image', 'url("' + img + '")'); - } else { - $("#blur-img").backgroundBlur(img); // 替换图像并淡出 - } - + $("#blur-img").backgroundBlur(img); // 替换图像并淡出 $("#blur-img").animate({opacity:"1"}, 2000); // 背景更换特效 } else { animate = true; // 等待图像加载完 @@ -475,8 +505,8 @@ function loadList(list) { addItem(i + 1, tmpMusic.name, tmpMusic.artist, tmpMusic.album); - // 只有网易云和虾米音乐源的歌曲进行链接记录(其它音乐链接均有有效期限制,重新显示列表时清空处理) - if(tmpMusic.source != "netease" && tmpMusic.source != "xiami") tmpMusic.url = ""; + // 只有网易云的歌曲进行链接记录(其它音乐链接均有有效期限制,重新显示列表时清空处理) + if(tmpMusic.source != "netease") tmpMusic.url = ""; } if(i == 0) { addListbar("nodata"); // 列表中没有数据 diff --git a/js/lyric.js b/js/lyric.js index 6c00198..0e0d7b0 100644 --- a/js/lyric.js +++ b/js/lyric.js @@ -1,8 +1,8 @@ /************************************************** - * MKOnlinePlayer v2.2 + * MKOnlinePlayer v2.31 * 歌词解析及滚动模块 * 编写:mengkun(http://mkblog.cn) - * 时间:2017-3-26 + * 时间:2017-9-13 *************************************************/ var lyricArea = $("#lyric"); // 歌词显示容器 diff --git a/js/musicList.js b/js/musicList.js index b530b49..dbcfc3f 100644 --- a/js/musicList.js +++ b/js/musicList.js @@ -77,7 +77,7 @@ var musicList = [ pic_id: "2946691234868155", // 封面ID lyric_id: "436514312", // 歌词ID pic: "https://p3.music.126.net/34YW1QtKxJ_3YnX9ZzKhzw==/2946691234868155.jpg", // 专辑图片 - url: "https://p2.music.126.net/7o5D4dA6271VktgawcbZFA==/18665309393829604.mp3" // mp3链接 + url: "https://p2.music.126.net/7o5D4dA6271VktgawcbZFA==/18665309393829604.mp3" // mp3链接(此项建议不填,因为各大音乐平台的外链有效期都较短……) }, // 下面演示插入各个平台的音乐。。。 { @@ -114,7 +114,7 @@ var musicList = [ pic_id: "81175", lyric_id: "81175", pic: "https://pic.xiami.net/images/album/img58/1258/66271400572139.jpg@300h_300w_100q_1c.jpg", - url: "https://om6.alicdn.com/258/1258/6627/81175_60243588_h.mp3?auth_key=31b6f2878c1e29b769cbb6b63d2da843-1505098800-0-null" + url: "" // 虾米的外链有效期较短,插入时 url [必须]设置空值,播放时再临时抓取 }, { id: "2a24dea6c74884195fe5b9732fd95ca8", diff --git a/js/player.js b/js/player.js index 09efbce..356279d 100644 --- a/js/player.js +++ b/js/player.js @@ -1,8 +1,8 @@ /************************************************** - * MKOnlinePlayer v2.3 + * MKOnlinePlayer v2.31 * 播放器主功能模块 * 编写:mengkun(http://mkblog.cn) - * 时间:2017-9-3 + * 时间:2017-9-12 *************************************************/ // 播放器功能配置 var mkPlayer = { @@ -16,7 +16,7 @@ var mkPlayer = { dotshine: true, // 是否开启播放进度条的小点闪动效果[不支持IE](true/false) *开启后会有些卡 mdotshine: false, // 是否开启[移动端]播放进度条的小点闪动效果[不支持IE](true/false) volume: 0.6, // 默认音量值(0~1之间) - version: "v2.3", // 播放器当前版本号(仅供调试) + version: "v2.31", // 播放器当前版本号(仅供调试) debug: false // 是否开启调试模式(true/false) }; @@ -202,6 +202,7 @@ function initAudio() { rem.audio[0].addEventListener('error', audioErr); // 播放器错误处理 } + // 播放音乐 // 参数:要播放的音乐数组 function play(music) { diff --git a/plugns/Meting.php b/plugns/Meting.php index fbedd3d..538a69e 100644 --- a/plugns/Meting.php +++ b/plugns/Meting.php @@ -3,7 +3,7 @@ * Meting music framework * https://i-meto.com * https://github.com/metowolf/Meting - * Version 1.3.8 + * Version 1.3.9 * * Copyright 2017, METO Sheel * Released under the MIT license @@ -153,15 +153,15 @@ class Meting 'method' => 'GET', 'url' => 'https://c.y.qq.com/soso/fcgi-bin/client_search_cp', 'body' => array( + 'format' => 'json', 'p' => $page, 'n' => $limit, 'w' => $keyword, 'aggr' => 1, 'lossless' => 1, 'cr' => 1, - 'platform' => 'yqq', + 'new_json' => 1, ), - 'decode' => 'jsonp2json', 'format' => 'data#song#list', ); break; @@ -321,12 +321,14 @@ class Meting case 'tencent': $API=array( 'method' => 'GET', - 'url' => 'https://c.y.qq.com/v8/fcg-bin/fcg_v8_album_info_cp.fcg', + 'url' => 'https://c.y.qq.com/v8/fcg-bin/fcg_v8_album_detail_cp.fcg', 'body' => array( 'albummid' => $id, - 'platform' => 'yqq', + 'platform' => 'mac', + 'format' => 'json', + 'newsong' => 1, ), - 'format' => 'data#list', + 'format' => 'data#getSongInfo', ); break; case 'xiami': @@ -406,7 +408,8 @@ class Meting 'begin' => 0, 'num' => $limit, 'order' => 'listen', - 'platform' => 'yqq', + 'platform' => 'mac', + 'newsong' => 1, ), 'format' => 'data#list', ); @@ -484,15 +487,14 @@ class Meting case 'tencent': $API=array( 'method' => 'GET', - 'url' => 'https://c.y.qq.com/qzone/fcg-bin/fcg_ucc_getcdinfo_byids_cp.fcg', + 'url' => 'https://c.y.qq.com/v8/fcg-bin/fcg_v8_playlist_cp.fcg', 'body' => array( - 'disstid' => $id, - 'utf8' => 1, - 'type' => 1, - 'platform' => 'yqq', + 'id' => $id, + 'format' => 'json', + 'newsong' => 1, + 'platform' => 'jqspaframe.json', ), - 'decode' => 'jsonp2json', - 'format' => 'cdlist#0#songlist', + 'format' => 'data#cdlist#0#songlist', ); break; case 'xiami': @@ -653,7 +655,7 @@ class Meting 'url' => 'https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg', 'body' => array( 'songmid' => $id, - 'g_tk' => 5381, + 'g_tk' => '5381', ), 'decode' => 'tencent_lyric', ); @@ -751,7 +753,7 @@ class Meting ), 'tencent'=>array( 'referer' => 'https://y.qq.com/portal/player.html', - 'cookie' => 'pgv_pvi=3832878080; pgv_si=s4066364416; pgv_pvid=3938077488; yplayer_open=1; qqmusic_fromtag=66; ts_last=y.qq.com/portal/player.html; ts_uid=5141451452; player_exist=1; yq_index=1', + 'cookie' => 'pgv_pvi=22038528; pgv_si=s3156287488; pgv_pvid=5535248600; yplayer_open=1; ts_last=y.qq.com/portal/player.html; ts_uid=4847550686; yq_index=0; qqmusic_fromtag=66; player_exist=1', 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', ), 'xiami'=>array( @@ -794,13 +796,6 @@ class Meting ); return $API; } - private function jsonp2json($jsonp) - { - if ($jsonp[0] !== '[' && $jsonp[0] !== '{') { - $jsonp = substr($jsonp, strpos($jsonp, '(')); - } - return trim($jsonp, '();'); - } private function tencent_singlesong($result) { $result=json_decode($result, 1); @@ -834,11 +829,9 @@ class Meting { $data=json_decode($result, 1); if (isset($data['data'][0]['uf']['url'])) { - $url=array( - 'url' => $data['data'][0]['uf']['url'], - 'br' =>$data['data'][0]['uf']['br']/1000, - ); - } elseif (isset($data['data'][0]['url'])) { + $data['data'][0]['url']=$data['data'][0]['uf']['url']; + } + if (isset($data['data'][0]['url'])) { $url=array( 'url' => $data['data'][0]['url'], 'br' => $data['data'][0]['br']/1000, @@ -859,10 +852,10 @@ class Meting 'method' => 'GET', 'url' => 'https://c.y.qq.com/base/fcgi-bin/fcg_musicexpress.fcg', 'body' => array( - 'json' => 3, - 'guid' => $GUID, + 'json' => 3, + 'guid' => $GUID, + 'format' => 'json', ), - 'decode' => 'jsonp2json', ); $KEY=json_decode($this->curl($API), 1); $KEY=$KEY['key']; @@ -918,8 +911,8 @@ class Meting } $urlt=str_replace('^', '0', urldecode($urlt)); $url=array( - 'url' => str_replace('http://','https://',urldecode($urlt)), - 'br' => 320, + 'url' => str_replace('http://','https://',urldecode($urlt)), + 'br' => 320, ); } else { $url=array( @@ -1002,7 +995,7 @@ class Meting } private function tencent_lyric($result) { - $result=$this->jsonp2json($result); + $result=substr($result,18,-1); if (!$this->_FORMAT) { return $result; } @@ -1098,13 +1091,13 @@ class Meting $data=$data['musicData']; } $result=array( - 'id' => $data['songmid'], - 'name' => $data['songname'], + 'id' => $data['mid'], + 'name' => $data['name'], 'artist' => array(), - 'album' => isset($data['albumname'])?$data['albumname']:$data['album']['name'], - 'pic_id' => $data['albummid'], - 'url_id' => $data['songmid'], - 'lyric_id' => $data['songmid'], + 'album' => trim($data['album']['title']), + 'pic_id' => $data['album']['mid'], + 'url_id' => $data['mid'], + 'lyric_id' => $data['mid'], 'source' => 'tencent', ); foreach ($data['singer'] as $vo) {