PixivPreviewer

在搜索页显示较大的预览图(请注意阅读详细信息)。Show preview of pictures in serach page.

目前為 2017-08-07 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name PixivPreviewer
  3. // @namespace
  4. // @version 1.11
  5. // @description 在搜索页显示较大的预览图(请注意阅读详细信息)。Show preview of pictures in serach page.
  6. // @author Ocrosoft
  7. // @match https://www.pixiv.net/search.php*
  8. // @match https://www.pixiv.net/member_illust.php?mode=medium*
  9. // @match https://www.pixiv.net/member_illust.php?mode=ugoira_view*
  10. // @match https://www.pixiv.net/ranking.php*
  11. // @grant none
  12. // @require http://code.jquery.com/jquery-2.1.4.min.js
  13. // @namespace
  14. // @namespace
  15. // ==/UserScript==
  16.  
  17. var mousePos;
  18.  
  19. function log(text) {
  20. console.log(text);
  21. }
  22.  
  23. function activePreview() {
  24. $('._layout-thumbnail').parent().mouseover(function (e) {
  25. if (e.ctrlKey) {
  26. return;
  27. }
  28. if ($(e.relatedTarget.parentNode).hasClass('pixivPreview')) {
  29. return;
  30. }
  31. var imgNode = this.children[0];
  32. // 鼠标位置
  33. mousePos = { x: e.pageX, y: e.pageY };
  34. // Div
  35. var previewDiv = document.createElement('div');
  36. $(previewDiv).css({ 'position': 'absolute', 'z-index': '999999' });
  37. $(previewDiv).addClass('pixivPreview');
  38. // 添加Div
  39. $('body')[0].appendChild(previewDiv);
  40. // 加载中图片
  41. var loadingImg = new Image();
  42. loadingImg.src = 'https://raw.githubusercontent.com/shikato/pixiv_sk/master/loading.gif';
  43. $(loadingImg).css('position', 'absolute');
  44. previewDiv.appendChild(loadingImg);
  45. // 要显示图片
  46. var loadImg = new Image();
  47. previewDiv.appendChild(loadImg);
  48. // 表示显示的是原图的图标
  49. var originIcon = new Image();
  50. originIcon.src = 'https://source.pixiv.net/www/images/pixivcomic-favorite.png';
  51. $(originIcon).css({ 'position': 'absolute', 'bottom': '0px', 'right': '0px', 'display': 'none' });
  52. previewDiv.appendChild(originIcon);
  53. // 点击图标新网页打开原图
  54. $(originIcon).click(function () {
  55. window.open($(previewDiv).children('img')[1].src);
  56. });
  57. $(previewDiv).css({ 'left': mousePos.x + 'px', 'top': mousePos.y + 'px' });
  58.  
  59. function viewImages(imgs, index, imgsOrigin) {
  60. if (!imgs || imgs.length == 0) return;
  61. if (index < 0) return;
  62. if (!imgsOrigin || imgsOrigin.length == 0 || imgs.length != imgsOrigin.length) return;
  63. if (!index) index = 0;
  64.  
  65. if ($(previewDiv).children('script').length == 0) {
  66. // 绑定点击事件,Ctrl+左键 单击切换原图
  67. loadImg.addEventListener('click', function (ev) {
  68. // 按住 Ctrl 来回切换原图
  69. if (ev.ctrlKey) {
  70. if (loadImg.src.indexOf('origin') == -1) {
  71. viewImages(allImgsOrigin, parseInt($($('.pixivPreview').children('img')[1]).attr('data-index')), allImgs);
  72. } else {
  73. viewImages(allImgs, parseInt($($('.pixivPreview').children('img')[1]).attr('data-index')), allImgsOrigin);
  74. }
  75. }
  76. // 按住 Shift 点击图片新标签页打开原图
  77. else if (ev.shiftKey) {
  78. window.open(allImgsOrigin[parseInt($($('.pixivPreview').children('img')[1]).attr('data-index'))]);
  79. }
  80. });
  81. }
  82. // 多图时绑定点击事件,点击图片切换到下一张
  83. if (index == 0 && imgs.length != 1 && $(previewDiv).children('._work').length == 0) {
  84. loadImg.addEventListener('click', function (e) {
  85. if (e.ctrlKey || e.shiftKey) return;
  86. var newIndex = parseInt($($('.pixivPreview').children('img')[1]).attr('data-index')) + 1;
  87. if (newIndex == allImgs.length) newIndex = 0;
  88. $('.pixivPreview').children('div').children('div').children('span')[0].innerHTML = (newIndex + 1) + '/' + allImgs.length;
  89. if (loadImg.src.indexOf('origin') == -1) {
  90. viewImages(allImgs, newIndex, allImgsOrigin);
  91. } else {
  92. viewImages(allImgsOrigin, newIndex, allImgs);
  93. }
  94. });
  95. }
  96.  
  97. // 右上角张数标记
  98. if (imgs.length != 1 && index == 0 && $(previewDiv).children('._work').length == 0) {
  99. var iconDiv = document.createElement('div');
  100. iconDiv.innerHTML = '<div class="page-count"><div class="icon"></div><span>1/' + imgs.length + '</span></div>';
  101. $(iconDiv).addClass('_work');
  102. $(iconDiv).css({ 'position': 'absolute', 'top': '0px', 'display': 'none' });
  103. previewDiv.appendChild(iconDiv);
  104. }
  105.  
  106. // 预加载
  107. loadImg.src = '';
  108. $(loadImg).css({ 'width': '', 'height': '', 'display': 'none' });
  109. $(loadingImg).css('display', '');
  110. $(originIcon).css('display', 'none');
  111. $(iconDiv).css({ 'display': 'none' });
  112. loadImg.addEventListener('load', function () {
  113. if (loadImg.src.indexOf('githubusercontent') != -1) return;
  114. // 调整图片大小
  115. var width = loadImg.width, screenWidth = document.documentElement.clientWidth;
  116. var height = loadImg.height, screenHeight = document.documentElement.clientHeight;
  117. var viewHeight, viewWidth;
  118. // 长图
  119. if (height > width) {
  120. viewHeight = screenHeight / 2;
  121. viewWidth = viewHeight / height * width;
  122. var scale = 1.0;
  123. while (viewWidth * scale > screenWidth / 2) {
  124. scale -= 0.01;
  125. }
  126. }
  127. // 宽图
  128. else {
  129. viewWidth = screenWidth / 2;
  130. viewHeight = viewWidth / width * height;
  131. var scale = 1.0;
  132. while (viewHeight * scale > screenHeight / 2) {
  133. scale -= 0.01;
  134. }
  135. }
  136. $(loadImg).css({ 'height': viewHeight * scale + 'px', 'width': viewWidth * scale + 'px' });
  137. $(previewDiv).css({ 'height': viewHeight * scale + 'px', 'width': viewWidth * scale + 'px' });
  138. $(loadingImg).css({ 'left': viewWidth * scale / 2 - 24 + 'px', 'top': viewHeight * scale / 2 - 24 + 'px' });
  139. $(loadImg).css('display', '');
  140. $(loadingImg).css('display', 'none');
  141. $(iconDiv).css({ 'display': '' });
  142. if (loadImg.src.indexOf('origin') != -1) {
  143. $(originIcon).css({ 'display': '' });
  144. } else {
  145. $(originIcon).css({ 'display': 'none' });
  146. }
  147. // 调整图片位置
  148. adjustDivPos(loadImg, previewDiv, screenWidth, screenHeight);
  149. // 第一次显示预览时将图片列表添加到末尾
  150. if ($(previewDiv).children('script').length == 0) {
  151. var s = document.createElement('script');
  152. // 输出预览图URL
  153. var tmp = "var allImgs=['";
  154. tmp += imgs[0];
  155. for (var i = 1; i < imgs.length; ++i) {
  156. tmp += "','" + imgs[i];
  157. }
  158. tmp += "'];";
  159. // 输出原图URL
  160. tmp += "var allImgsOrigin=['";
  161. tmp += imgsOrigin[0];
  162. for (var i = 1; i < imgsOrigin.length; ++i) {
  163. tmp += "','" + imgsOrigin[i];
  164. }
  165. tmp += "'];";
  166. // 输出
  167. s.innerHTML = tmp;
  168. previewDiv.appendChild(s);
  169. }
  170. });
  171. $(loadImg).attr('data-index', index);
  172. loadImg.src = imgs[index];
  173. }
  174.  
  175. var xmlHttp = new XMLHttpRequest();
  176. xmlHttp.onreadystatechange = function () {
  177. if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
  178. var resText = xmlHttp.responseText;
  179. // 单图
  180. try {
  181. // 取得图片地址
  182. // 预览图
  183. var imgSource = RegExp('<div class="_layout-thumbnail ui-modal-trigger">[^>]*>').
  184. exec(resText)[0].split('<')[2].split('\"')[1];
  185. // 原图
  186. var imgOrigin = RegExp('<div class="_illust_modal.*class="original-image').
  187. exec(resText)[0].split('data-src="')[1].split('\"')[0];
  188. viewImages([imgSource], 0, [imgOrigin]);
  189. return;
  190. } catch (e) {
  191. // empty
  192. }
  193. // 多图
  194. try {
  195. var img, imgs = [];
  196. var reg = new RegExp('https://i.pximg.net/img-master[^\"]*', 'g');
  197. while ((img = reg.exec(resText.split('<section class=\"manga\">')[1].
  198. split('</section>')[0])) !== null) {
  199. imgs.push(img[0]);
  200. }
  201. // 推出来的原图URL,暂时没有想到效率高的办法(imgs.length 次xmlHttpRequest)
  202. var imgsOrigin = [];
  203. for (var i = 0; i < imgs.length; ++i) {
  204. imgsOrigin.push(imgs[i].replace('img-master', 'img-original'));
  205. imgsOrigin[i] = imgsOrigin[i].replace('_master1200', '');
  206. }
  207. viewImages(imgs, 0, imgsOrigin);
  208. return;
  209. } catch (e) {
  210. // empty
  211. }
  212. }
  213. };
  214. // 动图
  215. if ($(this).hasClass('ugoku-illust')) {
  216. $(previewDiv).children().remove();
  217. previewDiv.innerHTML = '<iframe width="600px" height="50%" src="https://www.pixiv.net/member_illust.php?mode=ugoira_view&illust_id=' +
  218. $(imgNode.children[0]).attr('data-id') + '#animePreview"/>';
  219. $(previewDiv).children('iframe').css('display', 'none');
  220. var loadingImg = new Image();
  221. loadingImg.src = 'https://raw.githubusercontent.com/shikato/pixiv_sk/master/loading.gif';
  222. $(loadingImg).css('position', 'absolute');
  223. previewDiv.appendChild(loadingImg);
  224. return;
  225. }
  226. // 多图
  227. else if ($(imgNode.parentNode.parentNode).children('a').hasClass('multiple')) {
  228. xmlHttp.open('GET', 'https://www.pixiv.net/member_illust.php?mode=manga&illust_id=' +
  229. $(imgNode.children[0]).attr('data-id'), true);
  230. }
  231. // 单图
  232. else {
  233. xmlHttp.open('GET', 'https://www.pixiv.net/member_illust.php?mode=medium&illust_id=' +
  234. $(imgNode.children[0]).attr('data-id'), true);
  235. }
  236. xmlHttp.send(null);
  237. });
  238. $('._layout-thumbnail').parent().mouseout(function (e) {
  239. // 鼠标移动到预览图上
  240. if ($(e.relatedTarget).hasClass('pixivPreview') || $(e.relatedTarget).parents().hasClass('pixivPreview')) {
  241. $('.pixivPreview').mouseleave(function (ev) {
  242. if ($(ev.relatedTarget).hasClass('_work')) {
  243. // empty
  244. }
  245. else {
  246. $('.pixivPreview').remove();
  247. }
  248. });
  249. }
  250. // 非预览图上
  251. else {
  252. $('.pixivPreview').remove();
  253. }
  254. });
  255. $('._layout-thumbnail').parent().mousemove(function (e) {
  256. if (e.ctrlKey) {
  257. return;
  258. }
  259. var screenWidth = document.documentElement.clientWidth;
  260. var screenHeight = document.documentElement.clientHeight;
  261. mousePos.x = e.pageX; mousePos.y = e.pageY;
  262. adjustDivPos($('.pixivPreview').children('img')[1], $('.pixivPreview')[0], screenWidth, screenHeight);
  263. });
  264. $('._layout-thumbnail').addClass('prev');
  265. }
  266. function adjustDivPos(loadImg,previewDiv,screenWidth, screenHeight) {
  267. // 调整图片位置
  268. var divX = mousePos.x + 5, divY = mousePos.y + 5;
  269. if (mousePos.x > screenWidth / 2) {
  270. divX -= $(loadImg).css('width').split('px')[0];
  271. divX -= 10;
  272. }
  273. if ((mousePos.y - document.body.scrollTop) >
  274. screenHeight / 2) {
  275. divY -= $(loadImg).css('height').split('px')[0];
  276. divY -= 10;
  277. }
  278. $(previewDiv).css({ 'left': divX + 'px', 'top': divY + 'px' });
  279. }
  280.  
  281. (function () {
  282. // 动图预览辅助
  283. if (location.href.indexOf('medium') != -1 && location.href.indexOf('animePreview') != -1) {
  284. location.href = location.href.replace('medium', 'ugoira_view');
  285. return;
  286. } else if (location.href.indexOf('ugoira_view') != -1 && location.href.indexOf('animePreview') != -1) {
  287. var height = parseInt($('canvas').css('height').split('px'));
  288. var width = parseInt($('canvas').css('width').split('px'));
  289. var newHeight = 580 / width * height;
  290. $('canvas').css({ 'height': newHeight + 'px', 'width': 580 + 'px' });
  291. window.parent.iframeLoaded(newHeight, 580);
  292. return;
  293. }
  294. // 下载模式按钮
  295. var downloadButton = document.createElement('li');
  296. downloadButton.innerHTML = '<i class="_icon-12 _icon-up" style="transform: rotateX(180deg);border-radius: 100%;"></i>';
  297. downloadButton.className = 'item';
  298. $(downloadButton).css({ 'margin-bottom': '10px', 'opacity': '0.2' });
  299. $('#back-to-top').parent()[0].insertBefore(downloadButton, $($('#back-to-top').parent()[0]).children()[0]);
  300. // 点击开闭下载模式
  301. $(downloadButton).click(function () {
  302. if ($(downloadButton).css('opacity') == '0.2') {
  303. $(downloadButton).css('opacity', '0.5');
  304. $($(downloadButton).children()[0]).css({ 'background': 'green' });
  305. // 开启下载模式
  306. $('._layout-thumbnail').each(function () {
  307. $($(this).parent().children('img')[0]).css('display', '');
  308. }); // 显示多选框
  309. var t = $('._layout-thumbnail').parent().parent();
  310. for (var i = 0; i < t.length; ++i) {
  311. // 新的容器
  312. var checkDiv = document.createElement('div');
  313. // 覆盖在<a>上面的图
  314. var layer = new Image();
  315. layer.src = 'https://source.pixiv.net/www/images/common/transparent.gif';
  316. checkDiv.appendChild(layer);
  317. // 插入Div
  318. t[i].insertBefore(checkDiv, $(t[i]).children()[0]);
  319. // <a>移动进Div
  320. checkDiv.appendChild($(t[i]).children()[1]);
  321. $(layer).css({ 'height': $(layer).parent().css('height'), 'width': $(layer).parent().css('width'), 'position': 'absolute', 'z-index': '999999' });
  322. $(layer).click(function () {
  323. if ($(this).parent().children('a').children('img')[0].src.indexOf('unchecked') != -1) {
  324. $(this).parent().children('a').children('img')[0].src = 'https://raw.githubusercontent.com/Ocrosoft/PixivPreviewer/master/checked.png';
  325. } else {
  326. $(this).parent().children('a').children('img')[0].src = 'https://raw.githubusercontent.com/Ocrosoft/PixivPreviewer/master/unchecked.png';
  327. }
  328. });
  329. }
  330. } else {
  331. $(downloadButton).css('opacity', '0.2');
  332. $($(downloadButton).children()[0]).css({ 'background': '' });
  333. // 关闭下载模式
  334. var imgOriginList = []; var linkList = []; var imgCount = 0;
  335. var t = $('._layout-thumbnail').parent().parent().parent();
  336. for (var i = 0; i < t.length; ++i) {
  337. if ($(t[i]).children('div').children('a').children('img')[0].src.indexOf('unchecked') == -1) {
  338. var imgNode = $(t[i]).find('._layout-thumbnail').children('img')[0];
  339. // 多图
  340. if ($(imgNode.parentNode.parentNode).hasClass('multiple')) {
  341. linkList.push('https://www.pixiv.net/member_illust.php?mode=manga&illust_id=' +
  342. $(imgNode).attr('data-id'));
  343. }
  344. // 单图
  345. else {
  346. linkList.push('https://www.pixiv.net/member_illust.php?mode=medium&illust_id=' +
  347. $(imgNode).attr('data-id'));
  348. }
  349. }
  350. t[i].insertBefore($($(t[i]).children()[0]).children()[1], $(t[i]).children()[0]);
  351. $(t[i]).children('div').remove();
  352. }
  353. var xmlHttp = new XMLHttpRequest();
  354. xmlHttp.onreadystatechange = function () {
  355. if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
  356. var resText = xmlHttp.responseText;
  357. // 单图
  358. try {
  359. // 取得图片地址
  360. // 预览图
  361. var imgSource = RegExp('<div class="_layout-thumbnail ui-modal-trigger">[^>]*>').
  362. exec(resText)[0].split('<')[2].split('\"')[1];
  363. // 原图
  364. var imgOrigin = RegExp('<div class="_illust_modal.*class="original-image').
  365. exec(resText)[0].split('data-src="')[1].split('\"')[0];
  366. imgOriginList.push(imgOrigin);
  367. } catch (e) {
  368. // empty
  369. }
  370. // 多图
  371. try {
  372. var img, imgs = [];
  373. var reg = new RegExp('https://i.pximg.net/img-master[^\"]*', 'g');
  374. while ((img = reg.exec(resText.split('<section class=\"manga\">')[1].
  375. split('</section>')[0])) !== null) {
  376. imgs.push(img[0]);
  377. }
  378. // 推出来的原图URL,暂时没有想到效率高的办法(imgs.length 次xmlHttpRequest)
  379. var imgsOrigin = [];
  380. for (var i = 0; i < imgs.length; ++i) {
  381. imgsOrigin.push(imgs[i].replace('img-master', 'img-original'));
  382. imgsOrigin[i] = imgsOrigin[i].replace('_master1200', '');
  383. imgOriginList.push(imgsOrigin[i]);
  384. }
  385. } catch (e) {
  386. // empty
  387. }
  388. if (++imgCount == linkList.length) {
  389. $('._layout-thumbnail').each(function () {
  390. $(this).parent().children('img')[0].src = 'https://raw.githubusercontent.com/Ocrosoft/PixivPreviewer/master/unchecked.png';
  391. $($(this).parent().children('img')[0]).css('display', 'none');
  392. });
  393. var s = '';
  394. $(imgOriginList).each(function () {
  395. s += this + '\n';
  396. });
  397. prompt('复制到下载工具下载', s);
  398. } else {
  399. xmlHttp.open('GET', linkList[imgCount], true);
  400. xmlHttp.send(null);
  401. }
  402. }
  403. };
  404. if (linkList.length != 0) {
  405. xmlHttp.open('GET', linkList[0], true);
  406. xmlHttp.send(null);
  407. } else {
  408. $('._layout-thumbnail').each(function () {
  409. $($(this).parent().children('img')[0]).css('display', 'none');
  410. });
  411. }
  412. }
  413. });
  414. // 主要功能
  415. setInterval(function () {
  416. var t = $('._layout-thumbnail');
  417. if (!$(t[t.length - 1]).hasClass('prev')) {
  418. // 开启预览
  419. activePreview();
  420. // 表示是否选中的图标
  421. $('._layout-thumbnail').parent().each(function () {
  422. var checkIcon = new Image();
  423. checkIcon.src = 'https://raw.githubusercontent.com/Ocrosoft/PixivPreviewer/master/unchecked.png';
  424. $(checkIcon).css({ 'position': 'absolute', 'top': '0px', 'left': '0px', 'display': 'none' });
  425. this.appendChild(checkIcon);
  426. });
  427. }
  428. }, 500);
  429. })();
  430.  
  431. function iframeLoaded(height, width) {
  432. log('loaded');
  433. $('.pixivPreview').children('iframe').css({ 'width': width + 20 + 'px', 'height': height + 20 + 'px' });
  434. // 调整位置
  435. var divX = mousePos.x, divY = mousePos.y;
  436. var screenWidth = document.documentElement.clientWidth;
  437. var screenHeight = document.documentElement.clientHeight;
  438. if (mousePos.x > screenWidth / 2) {
  439. divX -= width;
  440. }
  441. if ((mousePos.y - document.body.scrollTop) >
  442. screenHeight / 2) {
  443. divY -= height;
  444. }
  445. $('.pixivPreview').css({ 'left': divX + 'px', 'top': divY + 'px' });
  446. $('.pixivPreview').children('iframe').css('display', '');
  447. $('.pixivPreview').children('img').remove();
  448. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址