微博图片全显示

同屏显示多图微博的全部大图。

  1. // ==UserScript==
  2. // @name 微博图片全显示
  3. // @namespace hzhbest
  4. // @include http://weibo.com/*
  5. // @include https://weibo.com/*
  6. // @include http://www.weibo.com/*
  7. // @include https://www.weibo.com/*
  8. // @description 同屏显示多图微博的全部大图。
  9. // @version 4.22
  10. // @grant GM_xmlhttpRequest
  11. // @grant unsafeWindow
  12. // @grant GM_getValue
  13. // @grant GM_setValue
  14. // @run-at document-end
  15. // @license GNU GPLv3
  16. // ==/UserScript==
  17.  
  18. (function () {
  19. // --这里是设置区-- //
  20. var topheight = 60; //微博顶栏高度
  21. var topspare = 125; //滚动预留顶部高度
  22. var autorefresh = true; //是否定时自动检测页面变化
  23. var loadLargeGif = GM_getValue('WBimgAll') || false; //是否载入大型动图
  24.  
  25. // --以下是代码区,请不要随意改动-- //
  26.  
  27. // http://weibo.com/2710065263/BmxiVDCgt?from=page_1005052710065263_profile&wvr=6&mod=weibotime&type=comment#_rnd1436436058420
  28. // http://weibo.com/2328516855/CnYCvixUq?type=comment#_rnd1436493435761
  29. var regex = /weibo\.com\/\d{8,10}\/[a-z0-9A-Z]{9}\??/;
  30. var cur = -1 // “当前图片”序
  31. pinit();
  32.  
  33. function pinit() {
  34. //检查是否已开大图,否则进入初始化进程;如果已开大图但网址已非单一微博网址则去除按钮;一秒检测一次
  35. var bpimg = document.querySelector("img.big_pic");
  36. console.log("matched?: ", regex.test(document.location.href));
  37. if (regex.test(document.location.href)) {
  38. //console.log(document.location.href);
  39. if (!bpimg) init();
  40. } else {
  41. var buttonbox = document.querySelector(".big_pic_b");
  42. if (!!buttonbox) buttonbox.parentNode.removeChild(buttonbox);
  43. }
  44. if (autorefresh) {
  45. setTimeout(pinit, 1000); //console.log("wait 1 sec");
  46. }
  47. }
  48.  
  49. function init() {
  50. //通过评论框架确定页面载入完成,通过附加媒体容器确定有需要展开大图的情况,都成立时进入处理进程
  51. var list_ul = document.querySelector("div.vue-recycle-scroller__item-view"); //评论框架
  52. var expbox = document.querySelector('div[class*="picture-box_row_"'); //附加媒体容器
  53. document.querySelector('main>div[class^="Main_full_"]').style =
  54. "width: 800px;";
  55. if (!list_ul && !expbox) {
  56. console.log("no1"); // * [no1]未加载评论框架,等候
  57. setTimeout(init, 1000);
  58. return;
  59. } else if (!!list_ul && !expbox) {
  60. console.log("no2", expbox); // * [no2]评论框架已加载却无附加媒体容器,退出
  61. //getlongtext()
  62. return;
  63. } else {
  64. // * [go]一切正常,开始处理
  65. // 应对超过九图的情况
  66. var nyimg = document.querySelector(
  67. '[class*="woo-box-justifyCenter picture_mask_"]'
  68. );
  69. if (!!nyimg) { //识别出超九图特征,将预览容器展开,以预览容器来获取图片
  70. nyimg.click();
  71. setTimeout(() => {
  72. expbox = document.querySelector('div[class*="picture-viewer_wrap_"]');
  73. console.log("go9");
  74. go(expbox);
  75. //console.log(expbox);
  76. }, 600);
  77. } else {
  78. console.log("go");
  79. go(expbox);
  80. }
  81. }
  82. }
  83.  
  84. function go(expbox) {
  85. var feedbox = document.querySelector(".vue-recycle-scroller__item-wrapper"); //评论区容器元素
  86. var appbox = document.querySelector("WB_app_view"); //应用容器??
  87. var videobox = document.querySelector('div[class*="card-video_videoBox_"'); //视频容器
  88. var maintextimgs = document.querySelectorAll(
  89. '[class^="detail_wbtext_"]>a[target]'
  90. ); //正文中的图片??
  91. var dbox =
  92. document.body.getElementsByTagName("main")[0].parentNode.parentNode; //主容器
  93. dbox.style.maxWidth = "none";
  94.  
  95. // Insert CSS
  96. var headID = document.getElementsByTagName("head")[0];
  97. var cssNode = creaElemIn("style", headID);
  98. cssNode.type = "text/css";
  99. cssNode.innerHTML = [
  100. ".big_pic{max-width: 890px;}",
  101. ".big_pic_n{max-width: 500px;}",
  102. ".big_pic:hover, .big_pic_n:hover{box-shadow: 0 0 30px 2px #f1ecdf;}",
  103. ".big_pic_poster{outline: 2px dashed #fcde44; outline-offset: -2px; cursor: pointer;}",
  104. ".big_pic_v{max-width: 90%; max-height: 80vh; cursor: pointer;}"
  105. ].join(""); //大图样式
  106. cssNode.innerHTML += [
  107. 'main>div[class^="Main_full_"] {width: auto !important;min-width:800px;}',
  108. ".WB_frame_c {width: auto !important; max-width: 920px; min-width: 600px;}",
  109. ".WB_text.W_f14, .repeat_list .list_box .WB_text, .WB_expand>.WB_text{width: 490px;}",
  110. ".WB_frame_c .media_box{display: none !important;}",
  111. 'div[node-type="comment_list"] .media_box{display: block !important;}',
  112. 'div[id^="Pl_Core_RecommendFeed__"]{right: 150px; width: 100px !important; max-height: 35px; overflow: hidden; transition: all ease 0.2s 0.5s;}',
  113. 'div[id^="Pl_Core_RecommendFeed__"]:hover{width: 300px !important; max-height: 1000px;}',
  114. 'div[id^="Pl_Core_RecommendFeed__"] .opt_box{display:none;}',
  115. 'div[id^="Pl_Core_RecommendFeed__"]:hover .opt_box{display: inline-block;}'
  116. ].join(""); //微博自身框架样式
  117. cssNode.innerHTML += [
  118. ".big_pic_b{position: fixed; left: 10px; top: 200px;}",
  119. ".big_pic_btn{height: 20px; min-width: 50px; width: fit-content; padding: 3px; margin-bottom: 20px; border: 1px solid white; color: white; background: rgba(133,133,133,0.6); cursor: pointer; user-select: none;}",
  120. ".big_pic_btn:hover{background: rgba(133,133,200,0.6);}",
  121. ".big_pic_ns{margin-bottom: 20px; width: 62px; display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; grid-gap: 3px;}",
  122. ".big_pic_ns > div{font-size: 10px; line-height: 28px; text-align: right; height: 15px; width: 15px; background-clip: border-box; background-position: center; background-size: cover; padding: 3px; border: 1px solid #7a7a7a; color: white; text-shadow: 0 0 2px black,0 0 2px black,0 0 2px black; cursor: pointer; user-select: none; opacity: 0.7;}",
  123. ".big_pic_ns > div:hover{font-size: 0px; outline: 1px solid #f8f87b; opacity: 1;}",
  124. ".big_pic_ns > div.curr{outline: 3px solid #f87bce; opacity: 0.9;}"
  125. ].join(""); //按钮样式
  126.  
  127. var buttonbox = creaElemIn("div", document.body);
  128. buttonbox.className = "big_pic_b";
  129. var sclink = creaElemIn("div", buttonbox); //直达评论链接
  130. var tplink = creaElemIn("div", buttonbox); //直达页顶链接
  131. var nclink = creaElemIn("div", buttonbox); //图片限宽链接
  132. var n1link = creaElemIn("div", buttonbox); //首个图片链接
  133. var n2link = creaElemIn("div", buttonbox); //上个图片链接
  134. var nslink = creaElemIn("div", buttonbox); //图片导航按钮
  135. var n3link = creaElemIn("div", buttonbox); //下个图片链接
  136. var swmode = creaElemIn("div", buttonbox); //切换动图模式链接
  137.  
  138. sclink.className = "big_pic_btn";
  139. sclink.innerHTML = "直达评论";
  140. sclink.addEventListener(
  141. "click",
  142. function () {
  143. var commentbox = document.querySelector("div.wbpro-tab3") || document.querySelector("#composerEle");
  144. scrollto(getTop(commentbox) - topheight * 2);
  145. },
  146. false
  147. );
  148.  
  149. tplink.className = "big_pic_btn";
  150. tplink.innerHTML = "回到页顶";
  151. tplink.addEventListener(
  152. "click",
  153. function () {
  154. var headerbox = document.querySelector("header");
  155. scrollto(getTop(headerbox) - topheight * 2);
  156. },
  157. false
  158. );
  159.  
  160. if (!!videobox) {
  161. cssNode.innerHTML = [
  162. ".big_pic_sc{position: fixed; left:10px; padding: 3px; border: 1px solid white; color: white; background: rgba(133,133,133,0.6); cursor: pointer;} ",
  163. ".big_pic_sc{top: 430px}",
  164. ].join("");
  165. return;
  166. }
  167.  
  168. if (!!appbox) {
  169. //检测到应用容器(微博文章或视频)时退出
  170. // box.appendChild(appbox);
  171. // if (!!wrpbox) expbox.removeChild(wrpbox);
  172. // cssNode.innerHTML = [
  173. // '.media_box{display: none !important;}',
  174. // '.big_pic_sc{position: fixed; left:10px; padding: 3px; border: 1px solid white; color: white; background: rgba(133,133,133,0.6); cursor: pointer;} ',
  175. // '.big_pic_sc{top: 430px}'].join("");
  176. return;
  177. }
  178.  
  179. if (!!maintextimgs) {
  180. for (const i in maintextimgs) {
  181. if (/sinaimg.c(om|n)\/large/.test(maintextimgs[i].href)) {
  182. var mtimg = document.createElement("img");
  183. maintextimgs[i].parentNode.insertBefore(mtimg, maintextimgs[i]);
  184. mtimg.src = maintextimgs[i].href;
  185. mtimg.style =
  186. "border: 3px dotted #64882e; width: auto !important; height: auto !important; max-width: 500px;";
  187. maintextimgs[i].parentNode.removeChild(maintextimgs[i]);
  188. }
  189. }
  190. }
  191.  
  192. //超过九图的应对
  193. var imgboxes;
  194. if (!!expbox.querySelector('[class*="picture-viewer_preview_"]')) {
  195. console.log("nine imgs");
  196. imgboxes = expbox.querySelectorAll(
  197. '[class*="picture-viewer_listContent_"]>div>div'
  198. );
  199. console.log(imgboxes.length);
  200. } else {
  201. imgboxes = expbox.querySelectorAll(
  202. 'div[class*="woo-box-item-inlineBlock picture_item_"]'
  203. );
  204. }
  205.  
  206. // 建立大图框架,用于插入大图
  207. var bpboxes = [],
  208. imgsrc,
  209. imgn,
  210. imgl = imgboxes.length;
  211. var _limited = false;
  212. var root = expbox.parentNode;
  213. nslink.className = "big_pic_ns";
  214. var nslinks = [];
  215.  
  216. var j = 0;
  217. for (var i = 0; i < imgl; i++) {
  218. //提取大图
  219. // https://wx2.sinaimg.cn/orj360/006QkcF9ly1gz75df9qmuj30nn061dj1.jpg
  220. // https://wx2.sinaimg.cn/large/006QkcF9ly1gz75df9qmuj30nn061dj1.jpg
  221. // https://wx4.sinaimg.cn/large/002MwiQagy1gz7le15xtyj60k06851kx02.jpg
  222. // https://wx3.sinaimg.cn/large/003nJ9EBly1hakhpjuqugj60dc336n5l02.jpg
  223. bpboxes[i] = creaElemIn("div", root);
  224. nslinks[i] = creaElemIn("div", nslink);
  225. nslinks[i].innerHTML = (i + 1);
  226. nslinks[i].name = i;
  227. creaElemIn("br", root);
  228. var imgnode = imgboxes[i].querySelector("img");
  229. var imgvnode = imgboxes[i].querySelector("video"); //“动图”(实际上是mp4视频)
  230. // console.log('imgtest: #',i,/sinaimg.c(om|n)/.test(imgnode.src));
  231. if (/sinaimg.c(om|n)/.test(imgnode.src)) { // 普通大图提取
  232. if (/sinaimg.c(om|n)\/(orj|thumb)\d{3}/.test(imgnode.src)) {
  233. imgsrc = imgnode.src.replace(
  234. /(sinaimg\.c(om|n)\/)(orj|thumb)\d{3}/,
  235. "$1large"
  236. );
  237. } else if (/sinaimg.c(om|n)\/large/.test(imgnode.src)) {
  238. imgsrc = imgnode.src;
  239. }
  240. imgn = creaElemIn("img", bpboxes[i]);
  241. imgn.src = imgsrc;
  242. imgn.className = "big_pic";
  243. imgn.title = "[ " + (i + 1) + " / " + imgl + " ]";
  244. nslinks[i].style.backgroundImage = 'url("' + imgnode.src + '")';
  245. } else if (!!imgvnode) {
  246. if (/sinaimg.c(om|n)\/(orj|thumb)\d{3}/.test(imgvnode.poster)) { // 动图大图提取
  247. imgsrc = loadLargeGif
  248. ? imgvnode.poster.replace( // 动大图模式,使用封面的大图
  249. /(sinaimg\.c(om|n)\/)(orj|thumb)\d{3}/,
  250. "$1large"
  251. )
  252. : imgvnode.poster; // 封面模式,直接用封面
  253. } else if (/sinaimg.c(om|n)\/large/.test(imgvnode.poster)) { // 封面直接就是大图
  254. imgsrc = imgvnode.poster;
  255. }
  256. imgn = creaElemIn("img", bpboxes[i]);
  257. imgn.src = imgsrc;
  258. imgn.className = "big_pic" + ((loadLargeGif) ? "" : " big_pic_poster");
  259. imgn.title = "[ " + (i + 1) + " / " + imgl + " ] 点击以视频方式播放";
  260. imgn.onclick = function (event) {
  261. let pnode = event.target;
  262. let vnode = pnode.parentNode.getElementsByTagName("video")[0];
  263. pnode.style.display = "none";
  264. vnode.style.display = "block";
  265. vnode.play();
  266. console.log("p: ", "played");
  267. };
  268. nslinks[i].style.backgroundImage = 'url("' + imgvnode.poster + '")';
  269. bpboxes[i].appendChild(imgvnode); // 将动图视频附在动图大图上,点击显示
  270. imgvnode.className = "big_pic_v";
  271. imgvnode.controls = true;
  272. imgvnode.style.display = "none";
  273. imgvnode.addEventListener("ended", function (event) {
  274. let vnode = event.target;
  275. let pnode = vnode.parentNode.getElementsByTagName("img")[0];
  276. console.log("p: ", pnode);
  277. vnode.style.display = "none";
  278. pnode.style.display = "block";
  279. });
  280. // imgvnode.onclick = function (event) {
  281. // console.log("v: ", "clicked");
  282. // //(vnode.paused)? vnode.play() : vnode.pause();
  283. // };
  284. } else {
  285. j += 1;
  286. continue;
  287. }
  288. nslinks[i].addEventListener(
  289. "click",
  290. function (e) {
  291. scrollto(getTop(bpboxes[e.target.name]) - topspare + 25);
  292. },
  293. false
  294. );
  295. if (j == imgl) return;
  296. }
  297. if (j == imgl) {
  298. //没找到符合条件的大图,退出
  299. cssNode.innerHTML =
  300. ".big_pic_sc{position: fixed; left:10px; padding: 3px; border: 1px solid white; color: white; background: rgba(133,133,133,0.6); cursor: pointer;} .big_pic_sc{top: 430px}";
  301. return;
  302. }
  303. imgl = bpboxes.length;
  304. if (!!root) root.removeChild(expbox);
  305.  
  306. nclink.className = "big_pic_btn";
  307. nclink.innerHTML = "图片限宽";
  308. nclink.addEventListener(
  309. "click",
  310. function () {
  311. var i;
  312. if (_limited) {
  313. for (i = 0; i < imgl; i++) {
  314. bpboxes[i].querySelector("img").className = "big_pic";
  315. }
  316. _limited = false;
  317. } else {
  318. for (i = 0; i < imgl; i++) {
  319. bpboxes[i].querySelector("img").className = "big_pic_n";
  320. }
  321. _limited = true;
  322. }
  323. },
  324. false
  325. );
  326.  
  327. n1link.className = "big_pic_btn";
  328. n1link.innerHTML = "△首个图片";
  329. n1link.addEventListener(
  330. "click",
  331. function () {
  332. scrollto(getTop(bpboxes[0]) - topspare +25);
  333. },
  334. false
  335. );
  336.  
  337. n2link.className = "big_pic_btn";
  338. n2link.innerHTML = "▲上个图片";
  339. n2link.addEventListener(
  340. "click",
  341. function () {
  342. var t = document.documentElement.scrollTop;
  343. for (var j = imgl - 1; j >= 0; j--) {
  344. if (t > getTop(bpboxes[j]) + bpboxes[j].offsetHeight - topspare) {
  345. scrollto(getTop(bpboxes[j]) - topspare + 25);
  346. return;
  347. }
  348. }
  349. },
  350. false
  351. );
  352.  
  353. n3link.className = "big_pic_btn";
  354. n3link.innerHTML = "▼下个图片";
  355. n3link.addEventListener(
  356. "click",
  357. function () {
  358. var t = document.documentElement.scrollTop;
  359. for (var j = 0; j < imgl; j++) {
  360. if (t < getTop(bpboxes[j]) - topspare) {
  361. scrollto(getTop(bpboxes[j]) - topspare + 25);
  362. return;
  363. }
  364. }
  365. },
  366. false
  367. );
  368.  
  369. swmode.className = "big_pic_btn";
  370. swmode.innerHTML = "↔切换动图模式";
  371. swmode.title = "切换为" + ((loadLargeGif) ? "显示封面静图" : "显示动图大图") + "并刷新页面";
  372. swmode.addEventListener(
  373. "click",
  374. function () {
  375. loadLargeGif = !loadLargeGif;
  376. GM_setValue('WBimgAll', loadLargeGif);
  377. location.reload();
  378. },
  379. false
  380. );
  381.  
  382. waitscroll();
  383.  
  384. document.onscroll = function () {
  385. var t = document.documentElement.scrollTop; // 当前滚动位置(视框顶y)
  386. var w = window.innerHeight; // 当前视框高度
  387. var percentage = 1 / 4; // 视框内“注视框”距视框顶底距离(1-2*percentage 为注视框高度占比)
  388. var linetop = t + w * percentage - topspare; // 注视框顶位置
  389. var linebtm = t + w * (1 - percentage); // 注视框底位置
  390. var j, vh, vhmax = 0; // 检查图片序、图片在注视框内高度、注视框内最大高度
  391. if (getTop(bpboxes[0]) >= linebtm || getTop(bpboxes[imgl - 1]) + bpboxes[imgl - 1].offsetHeight <= linetop) {
  392. cur = -1; // 若首图在注视框底之下或末图在注视框顶之上,则无当前图
  393. } else {
  394. for (j = imgl - 1; j >= 0; j--) { // 从底部检查各图片
  395. let ti = getTop(bpboxes[j]), hi = bpboxes[j].offsetHeight; // 检查图片位置、检查图片高度
  396. if (ti < linebtm && (ti + hi) > linetop) { // 若图片顶端在注视框底之上、底端在注视框顶之下
  397. vh = Math.min(linebtm, ti + hi) - Math.max(linetop, ti); // 计算注视框内高度
  398. if (vh >= vhmax) { // 当检查图片拥有更大的注视框内高度,则其为“当前图片”(等高则更前)
  399. vhmax = vh;
  400. cur = j;
  401. }
  402. }
  403. }
  404. }
  405. if (cur !== -1) {
  406. for (j = imgl - 1; j >= 0; j--) {
  407. if (j !== cur) {
  408. nslinks[j].classList.remove("curr");
  409. } else {
  410. nslinks[j].classList.add("curr");
  411. }
  412. }
  413. } else {
  414. for (j = imgl - 1; j >= 0; j--) {
  415. if (j !== cur) {
  416. nslinks[j].classList.remove("curr");
  417. }
  418. }
  419. }
  420. };
  421. }
  422.  
  423. function waitscroll() {
  424. //等待页面完全载入再滚动
  425. var list_ul = document.querySelector("div.list_ul"); //↓等待评论框架载入,如果评论框架就位就等待评论区或无评论提示载入,再视滚动位置判断
  426. if (
  427. !list_ul ||
  428. !list_ul.getElementsByTagName("div")[0] ||
  429. !document.querySelector("div.tips_rederror") ||
  430. document.documentElement.scrollTop < topheight + 70
  431. ) {
  432. setTimeout(waitscroll, 300); //console.log("wait");
  433. return;
  434. } else {
  435. scrollto(topheight); //console.log("scroll");
  436. }
  437. }
  438.  
  439. function scrollto(pos) {
  440. //滚动
  441. document.documentElement.scrollTop = pos;
  442. }
  443.  
  444. // Create an element
  445. function creaElemIn(tagname, destin) {
  446. var theElem = destin.appendChild(document.createElement(tagname));
  447. return theElem;
  448. }
  449. // Get the first element by xpath
  450. function getElem(xpath) {
  451. return document
  452. .evaluate(
  453. xpath,
  454. document,
  455. null,
  456. XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
  457. null
  458. )
  459. .snapshotItem(0);
  460. }
  461. // Get the absolute top of an element
  462. function getTop(e) {
  463. var offset = e.offsetTop;
  464. if (e.offsetParent != null) offset += getTop(e.offsetParent);
  465. return offset;
  466. }
  467.  
  468. })();

QingJ © 2025

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