// ==UserScript== // @name Pixiv Previewer // @namespace https://github.com/Ocrosoft/PixivPreviewer // @version 1.96 // @description 显示大图预览,按热门度排序(pixiv_sk)。Show Preview, Sort by favorite numbers(pixiv_sk). // @author Ocrosoft // @match *://www.pixiv.net/search.php* // 作品页主页 // @match *://www.pixiv.net/member.php?id=* // 作品页其他 // @match *://www.pixiv.net/member_illust.php?id=* // 作品页(动画预览) // @match *://www.pixiv.net/member_illust.php?mode=* // @match *://www.pixiv.net/ranking.php* // @match *://www.pixiv.net/bookmark_new_illust.php* // @match *://www.pixiv.net/discovery* // @match *://www.pixiv.net/ // @match *://www.pixiv.net/new_illust.php* // @match *://www.pixiv.net/cate_r18.php // @match *://www.pixiv.net/bookmark.php* // @match *://www.pixiv.net/stacc* // @grant none // @compatible Chrome // @compatible FireFox // @downloadURL none // ==/UserScript== /*function ErrorReport(msg) { var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://peer.ocrosoft.com/err.php?url=' + encodeURIComponent(location.href) + '&msg=' + msg, true); xhr.send(null); } try { $(); } catch (e) { ErrorReport('No JQuery'); //return; }*/ try { $(); } catch(e) { var script = document.createElement('script'); script.src = 'https://code.jquery.com/jquery-3.3.1.slim.min.js'; document.head.appendChild(script); } /** * ---------------------------------------- 以下为 设置 部分 ---------------------------------------- * -------------------------------------------- Settings -------------------------------------------- */ // 注意: 修改设置请使用设置页面,此处修改无效 // 是否开启预览功能 var ENABLE_PREVIEW = true; // 预览的图片质量,0:普通;1:原图 var PREVIEW_QUALITY = 0; // 不显示多图切换时的加载图片 var HIDE_LOADING_IN_NEXTPIC = false; // 是否开启排序功能 var ENABLE_SORT = true; // 每次加载的页数 var GETTING_PAGE_COUNT = 3; // 收藏量在此以下的不显示 var FAV_FILTER = 3; // 隐藏已收藏图片 var HIDE_FAVORITE = false; // true,使用新标签页打开图片;false,保持默认 var IS_LINK_BLANK = true; // 语言,根据页面自动确定,其他不支持的语言默认使用English,可以修改成0使用简体中文 // 0:简体中文 // 1:English var lang = 1; /** * ---------------------------------------- 以下为 预览功能 部分 ---------------------------------------- */ /** * 搜索页、发现页节点结构 * section, [dataDiv] * -div, [picList] * --div * ---figure * ----div, [picDiv] * -----a, [picHref] * -----div(菜单) * ================== * 关注页节点结构 * div, [dataDiv], [infoDiv] * -div, [picList] * --div, * ---figure * ----div, [picDiv] * -----a, [picHref] * -----div(菜单) * ================== * 作品页、主页节点结构 * div, [dataDiv] * -ul, [picList] * --li * ---a, [picHref] * ----div, [picDiv] * -----img * -----div(菜单) * 排行榜页 * div, [dataDiv] * -div, [picList] * --section * ---div(这是排名) * ---div * ----a, [picHref] * -----div, [picDiv] * ------img * ------div(菜单) */ var SearchPage = 0, FollowPage = 1, DiscoveryPage = 2, MemberPage = 3, HomePage = 4, RankingPage = 5, NewIllustPage = 6, R18Cate = 7, BookMarkPage = 8, StaccPage = 9; // 页面Id var CurrentPage = SearchPage; // 该页面属于什么页面 var dataDivSelector = ['#js-react-search-mid', '#js-mount-point-latest-following', '.gtm-illust-recommend-zone', '...', '...', '.ranking-items-container', '...', '...', '...', '...']; var infoDivSelector = ['#js-mount-point-search-result-list', '#js-mount-point-latest-following', '...', '...', '...', '...', '...', '...', '...', '...']; var dataDiv, infoDiv, picList, picDiv = [], picHref = []; // 相关元素,含义见上 var dataStr; // 更新后图片信息使用 json 保存在了 dataDiv 的 data-items 属性中 var imgData; // 保存解析后的 json var mousePos; // 鼠标位置 var SORT_END = false; // 是否排序完成 var show_origin = false; // 默认预览使用原图 var i; // 获取相关的元素 function getImageElements() { if (infoDivSelector[CurrentPage] == '...') { return; } dataDiv = $(dataDivSelector[CurrentPage]); infoDiv = $(infoDivSelector[CurrentPage]); dataStr = infoDiv.attr('data-items'); imgData = eval(dataStr); picList = dataDiv.children()[0]; var pics = $(picList).children(); picDiv = []; picHref = []; for (var i = 0; i < pics.length; i++) { if(pics[i].className != pics[0].className){ pics[i].remove(); pics.splice(i--,1); continue; } picDiv.push(pics[i].childNodes[0].childNodes[0]); $(picDiv[i]).attr('data-index', i); picHref.push(picDiv[i].childNodes[0]); $(picHref[i]).attr('data-index', i); $(picHref[i]).attr('data-id', imgData[i].illustId); } } // 动图预览在相关页面调用的函数(自动执行,非动图页面无操作) (function animePreview() { try { // 动图下载 if (location.href.indexOf('medium') != -1 && document.querySelectorAll('._ugoku-illust-player-container').length > 0) { var script = document.createElement('script'); script.src = 'https://greasyfork.org/scripts/30681/code/Pixiv.user.js'; document.body.appendChild(script); } // 全图预览调节并返回 canvas 大小 if (location.href.indexOf('medium') != -1 && location.href.indexOf('animePreview') != -1) { var itv = setInterval(function(){ if (document.querySelectorAll('canvas').length > 0) { clearInterval(itv); var canvas = document.querySelectorAll('canvas'); // 额,能用 jquery... $(canvas[0]).click(); var e, mouseX, mouseY, screenWidth, screenHeight, height, width, newHeight, newWidth, scale; scale = 1.0; mouseY = screenHeight = location.href.split('animePreview')[1]; mouseX = mouseY.split(',')[0]; mouseY = mouseY.split(',')[1]; screenWidth = screenHeight.split(',')[2]; screenHeight = screenHeight.split(',')[3]; height = parseInt(document.querySelector('canvas').style.height.split('px')); width = parseInt(document.querySelector('canvas').style.width.split('px')); if (height > width) { newHeight = screenHeight; newWidth = newHeight / height * width; if (mouseX > screenWidth / 2) { while (newWidth * scale > mouseX - 5) { scale -= 0.01; } } else { while (newWidth * scale > screenWidth - mouseX - 5) { scale -= 0.01; } } newHeight *= scale; newWidth *= scale; } else { if (mouseX > screenWidth / 2) { newWidth = mouseX - 5; } else { newWidth = screenWidth - mouseX - 5; } newHeight = newWidth / width * height; while (newHeight * scale > screenHeight) { scale -= 0.01; } newHeight *= scale; newWidth *= scale; } newHeight -= 50; newWidth -= 25; document.querySelector('canvas').style.height = newHeight + 'px'; document.querySelector('canvas').style.width = newWidth + 'px'; var div = document.createElement('div'); div.className = 'embed'; div.innerHTML = '
'; $($('canvas')[1]).parent().prepend(div); window.parent.iframeLoaded(newHeight + 30, newWidth + 30); //https://i.pximg.net/img-zip-ugoira/img/2019/03/30/17/13/18/73950472_ugoira1920x1080.zip //original":"https:\/\/i.pximg.net\/img-original\/img\/2019\/03\/30\/17\/13\/18\/73950472_ugoira0.jpg" var reg = new RegExp('original.*?http.*?img-original.*?ugoira.*?"'); var tmp = document.querySelector('html').innerHTML; // 去掉头尾不要的部分 var full = reg.exec(tmp)[0].split('":"')[1]; full = full.substring(0, full.length - 1); // 替换成下载地址 full = full.replace(/ugoira.*/, 'ugoira1920x1080.zip'); full = full.replace('img-original', 'img-zip-ugoira'); $('#dl_full').click(function() { window.open(full); $('canvas').click(); }); } }, 500); return; } } catch (e) { // } })(); // iframe 加载完成时调用(动图预览) // arg: canvas 元素高,canvas 元素宽 var callbackScript = document.createElement('script'); callbackScript.innerHTML = "function iframeLoaded(height,width){$('.pixivPreview').children('iframe').attr({'width':width,'height':height});$('.pixivPreview').children('iframe').css('display','');$('.pixivPreview').children('img').remove();}"; document.body.appendChild(callbackScript); // 测试图片是否有效 function validateImage(url) { url = url.replace('manga', 'manga_big'); url += '&page=0'; var xmlHttp = new XMLHttpRequest(); xmlHttp.open('GET', url, false); xmlHttp.send(null); var src = $($(xmlHttp.responseText)[$(xmlHttp.responseText).length - 1]).attr('src'); if (src.indexOf('.png') == -1) return true; else return false; } function preLoad(urls) { //return; for (i = 0; i < urls.length; i++) { var image = new Image(); image.src = urls[i]; } } function pixivPreviewer() { // 开启预览功能 function activePreview() { // 鼠标移动到图片上显示预览图 $(picHref).mouseover(function (e) { // 按住 Ctrl键 不显示预览图 if (e.ctrlKey) { return; } // 图片索引 var dataIndex = $(this).attr('data-index'); // 从预览图移动到图片上,不应再次显示 var tar = $(e.relatedTarget); var fFromPreviewElement = false; for (var i = 0; i < 3; i++) { if (tar.hasClass('pixivPreview') && tar.attr('data-index') == dataIndex) { fFromPreviewElement = true; break; } tar = tar.parent(); } if (fFromPreviewElement) { return; } // 鼠标位置 mousePos = { x: e.pageX, y: e.pageY }; // 预览 Div var previewDiv = document.createElement('div'); $(previewDiv).css({ 'position': 'absolute', 'z-index': '999999' }); $(previewDiv).addClass('pixivPreview'); $(previewDiv).attr('data-index', dataIndex); // 添加 Div 到 body $('.pixivPreview').remove(); $('body')[0].appendChild(previewDiv); // 加载中图片节点 var loadingImg = new Image(); loadingImg.src = 'https://raw.githubusercontent.com/shikato/pixiv_sk/master/loading.gif'; $(loadingImg).css('position', 'absolute'); $(loadingImg).attr('data-index', dataIndex); previewDiv.appendChild(loadingImg); // 要显示的预览图节点 var loadImg = new Image(); $(loadImg).attr('data-index', dataIndex).css({'height':'0px', 'width':'0px'}); previewDiv.appendChild(loadImg); // 表示显示的是原图的图标 var originIcon = new Image(); originIcon.src = 'https://source.pixiv.net/www/images/pixivcomic-favorite.png'; $(originIcon).css({ 'position': 'absolute', 'bottom': '0px', 'right': '0px', 'display': 'none' }); $(originIcon).attr('data-index', dataIndex); previewDiv.appendChild(originIcon); // 点击图标新网页打开原图 $(originIcon).click(function () { window.open($(previewDiv).children('img')[1].src); }); $(previewDiv).css({ 'left': mousePos.x + 'px', 'top': mousePos.y + 'px' }); if ($(picDiv[dataIndex]).find('._work').length > 0){ $($(picDiv[dataIndex]).find('._work')[0]).addClass('prev'); } else $(picDiv[dataIndex]).addClass('prev'); // 显示预览图 // args: 图片地址数组,下标,原图地址数组 function viewImages(imgs, index, imgsOrigin) { if (!imgs || imgs.length == 0) return; if (index < 0) return; if (!imgsOrigin || imgsOrigin.length == 0 || imgs.length != imgsOrigin.length) return; if (!index) index = 0; // 绑定点击事件,Ctrl+左键 单击切换原图 if ($(previewDiv).children('script').length == 0) { loadImg.addEventListener('click', function (ev) { // 按住 Ctrl 来回切换原图 if (ev.ctrlKey) { show_origin = !show_origin; viewImages(imgs, index, imgsOrigin); } // 按住 Shift 点击图片新标签页打开原图 else if (ev.shiftKey) { window.open(allImgsOrigin[parseInt($($('.pixivPreview').children('img')[1]).attr('img-index'))]); } }); } // 多图时绑定点击事件,点击图片切换到下一张 if (index == 0 && imgs.length != 1 && $(previewDiv).children('._work').length == 0) { loadImg.addEventListener('click', function (e) { if (e.ctrlKey || e.shiftKey) return; var newIndex = parseInt($($('.pixivPreview').children('img')[1]).attr('img-index')) + 1; if (newIndex == allImgs.length) newIndex = 0; $('.pixivPreview').children('div').children('div').children('span')[0].innerHTML = (newIndex + 1) + '/' + allImgs.length; viewImages(allImgs, newIndex, allImgsOrigin); if (newIndex + 3 <= allImgs.length) { preLoad((show_origin ? allImgsOrigin : allImgs).slice(newIndex + 3, newIndex + 4)); } }); } // 右上角张数标记 if (imgs.length != 1 && index == 0 && $(previewDiv).children('._work').length == 0) { var iconDiv = document.createElement('div'); iconDiv.innerHTML = '
1/' + imgs.length + '
'; $(iconDiv).addClass('_work'); $(iconDiv).css({ 'position': 'absolute', 'top': '0px', 'display': 'none', 'right': '0px'}); $(iconDiv).attr('data-index', dataIndex); $(iconDiv.childNodes).attr('data-index', dataIndex); previewDiv.appendChild(iconDiv); } // 预加载 // 不隐藏多图加载中图片 if (!HIDE_LOADING_IN_NEXTPIC) { // 显示加载中图片 $(loadingImg).css('display', ''); // 所有图未加载完成不显示 $(loadImg).css('display', 'none'); } else { // 第一次显示时未加载完成不显示 if ($(previewDiv).children('script').length == 0) { $(loadImg).css('display', 'none'); } } $(originIcon).css('display', 'none'); $(iconDiv).css({ 'display': 'none' }); // 图片预加载完成 loadImg.addEventListener('load', function () { if (loadImg.src == '') return; // 调整图片大小 var screenWidth = document.documentElement.clientWidth; var screenHeight = document.documentElement.clientHeight; var viewHeight, viewWidth; // 调整图片位置和大小 var ret = adjustDivPos(loadImg, previewDiv, screenWidth, screenHeight); viewWidth = ret[0]; viewHeight = ret[1]; $(loadingImg).css({ 'left': viewWidth / 2 - 24 + 'px', 'top': viewHeight / 2 - 24 + 'px' }); $(loadImg).css('display', ''); $(loadingImg).css('display', 'none'); $(iconDiv).css({ 'display': '' }); if (loadImg.src.indexOf('origin') != -1) { $(originIcon).css({ 'display': '' }); } else { $(originIcon).css({ 'display': 'none' }); } // 第一次显示预览时将图片列表添加到末尾 // 第一次显示时,预加载后面3张 if ($(previewDiv).children('script').length == 0) { var s = document.createElement('script'); // 输出预览图URL var tmp = "var allImgs=['"; tmp += imgs[0]; for (var i = 1; i < imgs.length; ++i) { tmp += "','" + imgs[i]; } tmp += "'];"; // 输出原图URL tmp += "var allImgsOrigin=['"; tmp += imgsOrigin[0]; for (i = 1; i < imgsOrigin.length; ++i) { tmp += "','" + imgsOrigin[i]; } tmp += "'];"; // 输出 s.innerHTML = tmp; previewDiv.appendChild(s); var urls = show_origin ? imgsOrigin : imgs; if (urls.length > 4) urls = urls.slice(1, 4); else urls = urls.slice(1); preLoad(urls); } }); loadImg.addEventListener('error', function() { loadImg.src = (loadImg.src.indexOf('.jpg') != -1) ? (loadImg.src.replace('.jpg', '.png')) : (loadImg.src.replace('.png', '.jpg')); }); $(loadImg).attr('img-index', index); loadImg.src = show_origin ? imgsOrigin[index] : imgs[index]; } // 进行 http 请求,获取预览图链接 var xmlHttp = new XMLHttpRequest(); xmlHttp.onreadystatechange = function () { if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { var resText = xmlHttp.responseText; try { // 取得图片地址 // 预览图 var imgs = [], imgsOrigin = []; // 新格式的多图 var patt = /images\[\d*] = "[^"]*/g; while(true) { var imgSource = patt.exec(resText); if (imgSource == null) { // 是单图 if (imgs.length == 0) { // 判断错了,这是多图 try { var pageCount = /"pageCount":\d*,"bookmarkCount":/.exec(resText)[0]; pageCount = pageCount.split(',')[0].split(':')[1]; pageCount = parseInt(pageCount); if (pageCount != 1) { alert('脚本错误'); return; } } catch (ex) { // console.log(ex); } // 出错了就是单图了 imgs.push(RegExp('"regular":"http.*"').exec(resText)[0].split('":"')[1].split('\"')[0]); imgsOrigin.push(RegExp('"original":"http.*"').exec(resText)[0].split('":"')[1].split('\"')[0]); } break; } imgs.push(imgSource[0].split('"')[1]); } pageCount = imgs.length; // 单图就直接显示了 if (pageCount == 1) { viewImages([imgs], 0, [imgsOrigin]); return; } else { // JPG 和 PNG 的切换放在显示那边了 for (i = 0; i < pageCount; i++) { imgsOrigin.push(imgs[i].replace('master','original').replace('_master1200', '')); } viewImages(imgs, 0, imgsOrigin); // 显示第0张,预加载1,2,3张 var urls = show_origin ? imgsOrigin : imgs; if (urls.length > 4) urls = urls.slice(1, 4); else urls = urls.slice(1); //preLoad(urls); return; } } catch (e) { console.log(e); } } }; // 动图,illustType 值为2 if (imgData[dataIndex].illustType == 2) { $(previewDiv).children().remove(); var screenWidth = document.documentElement.clientWidth; var screenHeight = document.documentElement.clientHeight; previewDiv.innerHTML = '