- // ==UserScript==
- // @name 微博图片全显示
- // @namespace hzhbest
- // @include http://weibo.com/*
- // @include https://weibo.com/*
- // @include http://www.weibo.com/*
- // @include https://www.weibo.com/*
- // @description 同屏显示多图微博的全部大图。
- // @version 4.22
- // @grant GM_xmlhttpRequest
- // @grant unsafeWindow
- // @grant GM_getValue
- // @grant GM_setValue
- // @run-at document-end
- // @license GNU GPLv3
- // ==/UserScript==
-
- (function () {
- // --这里是设置区-- //
- var topheight = 60; //微博顶栏高度
- var topspare = 125; //滚动预留顶部高度
- var autorefresh = true; //是否定时自动检测页面变化
- var loadLargeGif = GM_getValue('WBimgAll') || false; //是否载入大型动图
-
- // --以下是代码区,请不要随意改动-- //
-
- // http://weibo.com/2710065263/BmxiVDCgt?from=page_1005052710065263_profile&wvr=6&mod=weibotime&type=comment#_rnd1436436058420
- // http://weibo.com/2328516855/CnYCvixUq?type=comment#_rnd1436493435761
- var regex = /weibo\.com\/\d{8,10}\/[a-z0-9A-Z]{9}\??/;
- var cur = -1 // “当前图片”序
- pinit();
-
- function pinit() {
- //检查是否已开大图,否则进入初始化进程;如果已开大图但网址已非单一微博网址则去除按钮;一秒检测一次
- var bpimg = document.querySelector("img.big_pic");
- console.log("matched?: ", regex.test(document.location.href));
- if (regex.test(document.location.href)) {
- //console.log(document.location.href);
- if (!bpimg) init();
- } else {
- var buttonbox = document.querySelector(".big_pic_b");
- if (!!buttonbox) buttonbox.parentNode.removeChild(buttonbox);
- }
- if (autorefresh) {
- setTimeout(pinit, 1000); //console.log("wait 1 sec");
- }
- }
-
- function init() {
- //通过评论框架确定页面载入完成,通过附加媒体容器确定有需要展开大图的情况,都成立时进入处理进程
- var list_ul = document.querySelector("div.vue-recycle-scroller__item-view"); //评论框架
- var expbox = document.querySelector('div[class*="picture-box_row_"'); //附加媒体容器
- document.querySelector('main>div[class^="Main_full_"]').style =
- "width: 800px;";
- if (!list_ul && !expbox) {
- console.log("no1"); // * [no1]未加载评论框架,等候
- setTimeout(init, 1000);
- return;
- } else if (!!list_ul && !expbox) {
- console.log("no2", expbox); // * [no2]评论框架已加载却无附加媒体容器,退出
- //getlongtext()
- return;
- } else {
- // * [go]一切正常,开始处理
- // 应对超过九图的情况
- var nyimg = document.querySelector(
- '[class*="woo-box-justifyCenter picture_mask_"]'
- );
- if (!!nyimg) { //识别出超九图特征,将预览容器展开,以预览容器来获取图片
- nyimg.click();
- setTimeout(() => {
- expbox = document.querySelector('div[class*="picture-viewer_wrap_"]');
- console.log("go9");
- go(expbox);
- //console.log(expbox);
- }, 600);
- } else {
- console.log("go");
- go(expbox);
- }
- }
- }
-
- function go(expbox) {
- var feedbox = document.querySelector(".vue-recycle-scroller__item-wrapper"); //评论区容器元素
- var appbox = document.querySelector("WB_app_view"); //应用容器??
- var videobox = document.querySelector('div[class*="card-video_videoBox_"'); //视频容器
- var maintextimgs = document.querySelectorAll(
- '[class^="detail_wbtext_"]>a[target]'
- ); //正文中的图片??
- var dbox =
- document.body.getElementsByTagName("main")[0].parentNode.parentNode; //主容器
- dbox.style.maxWidth = "none";
-
- // Insert CSS
- var headID = document.getElementsByTagName("head")[0];
- var cssNode = creaElemIn("style", headID);
- cssNode.type = "text/css";
- cssNode.innerHTML = [
- ".big_pic{max-width: 890px;}",
- ".big_pic_n{max-width: 500px;}",
- ".big_pic:hover, .big_pic_n:hover{box-shadow: 0 0 30px 2px #f1ecdf;}",
- ".big_pic_poster{outline: 2px dashed #fcde44; outline-offset: -2px; cursor: pointer;}",
- ".big_pic_v{max-width: 90%; max-height: 80vh; cursor: pointer;}"
- ].join(""); //大图样式
- cssNode.innerHTML += [
- 'main>div[class^="Main_full_"] {width: auto !important;min-width:800px;}',
- ".WB_frame_c {width: auto !important; max-width: 920px; min-width: 600px;}",
- ".WB_text.W_f14, .repeat_list .list_box .WB_text, .WB_expand>.WB_text{width: 490px;}",
- ".WB_frame_c .media_box{display: none !important;}",
- 'div[node-type="comment_list"] .media_box{display: block !important;}',
- 'div[id^="Pl_Core_RecommendFeed__"]{right: 150px; width: 100px !important; max-height: 35px; overflow: hidden; transition: all ease 0.2s 0.5s;}',
- 'div[id^="Pl_Core_RecommendFeed__"]:hover{width: 300px !important; max-height: 1000px;}',
- 'div[id^="Pl_Core_RecommendFeed__"] .opt_box{display:none;}',
- 'div[id^="Pl_Core_RecommendFeed__"]:hover .opt_box{display: inline-block;}'
- ].join(""); //微博自身框架样式
- cssNode.innerHTML += [
- ".big_pic_b{position: fixed; left: 10px; top: 200px;}",
- ".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;}",
- ".big_pic_btn:hover{background: rgba(133,133,200,0.6);}",
- ".big_pic_ns{margin-bottom: 20px; width: 62px; display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; grid-gap: 3px;}",
- ".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;}",
- ".big_pic_ns > div:hover{font-size: 0px; outline: 1px solid #f8f87b; opacity: 1;}",
- ".big_pic_ns > div.curr{outline: 3px solid #f87bce; opacity: 0.9;}"
- ].join(""); //按钮样式
-
- var buttonbox = creaElemIn("div", document.body);
- buttonbox.className = "big_pic_b";
- var sclink = creaElemIn("div", buttonbox); //直达评论链接
- var tplink = creaElemIn("div", buttonbox); //直达页顶链接
- var nclink = creaElemIn("div", buttonbox); //图片限宽链接
- var n1link = creaElemIn("div", buttonbox); //首个图片链接
- var n2link = creaElemIn("div", buttonbox); //上个图片链接
- var nslink = creaElemIn("div", buttonbox); //图片导航按钮
- var n3link = creaElemIn("div", buttonbox); //下个图片链接
- var swmode = creaElemIn("div", buttonbox); //切换动图模式链接
-
- sclink.className = "big_pic_btn";
- sclink.innerHTML = "直达评论";
- sclink.addEventListener(
- "click",
- function () {
- var commentbox = document.querySelector("div.wbpro-tab3") || document.querySelector("#composerEle");
- scrollto(getTop(commentbox) - topheight * 2);
- },
- false
- );
-
- tplink.className = "big_pic_btn";
- tplink.innerHTML = "回到页顶";
- tplink.addEventListener(
- "click",
- function () {
- var headerbox = document.querySelector("header");
- scrollto(getTop(headerbox) - topheight * 2);
- },
- false
- );
-
- if (!!videobox) {
- cssNode.innerHTML = [
- ".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}",
- ].join("");
- return;
- }
-
- if (!!appbox) {
- //检测到应用容器(微博文章或视频)时退出
- // box.appendChild(appbox);
- // if (!!wrpbox) expbox.removeChild(wrpbox);
- // cssNode.innerHTML = [
- // '.media_box{display: none !important;}',
- // '.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}'].join("");
- return;
- }
-
- if (!!maintextimgs) {
- for (const i in maintextimgs) {
- if (/sinaimg.c(om|n)\/large/.test(maintextimgs[i].href)) {
- var mtimg = document.createElement("img");
- maintextimgs[i].parentNode.insertBefore(mtimg, maintextimgs[i]);
- mtimg.src = maintextimgs[i].href;
- mtimg.style =
- "border: 3px dotted #64882e; width: auto !important; height: auto !important; max-width: 500px;";
- maintextimgs[i].parentNode.removeChild(maintextimgs[i]);
- }
- }
- }
-
- //超过九图的应对
- var imgboxes;
- if (!!expbox.querySelector('[class*="picture-viewer_preview_"]')) {
- console.log("nine imgs");
- imgboxes = expbox.querySelectorAll(
- '[class*="picture-viewer_listContent_"]>div>div'
- );
- console.log(imgboxes.length);
- } else {
- imgboxes = expbox.querySelectorAll(
- 'div[class*="woo-box-item-inlineBlock picture_item_"]'
- );
- }
-
- // 建立大图框架,用于插入大图
- var bpboxes = [],
- imgsrc,
- imgn,
- imgl = imgboxes.length;
- var _limited = false;
- var root = expbox.parentNode;
- nslink.className = "big_pic_ns";
- var nslinks = [];
-
- var j = 0;
- for (var i = 0; i < imgl; i++) {
- //提取大图
- // https://wx2.sinaimg.cn/orj360/006QkcF9ly1gz75df9qmuj30nn061dj1.jpg
- // https://wx2.sinaimg.cn/large/006QkcF9ly1gz75df9qmuj30nn061dj1.jpg
- // https://wx4.sinaimg.cn/large/002MwiQagy1gz7le15xtyj60k06851kx02.jpg
- // https://wx3.sinaimg.cn/large/003nJ9EBly1hakhpjuqugj60dc336n5l02.jpg
- bpboxes[i] = creaElemIn("div", root);
- nslinks[i] = creaElemIn("div", nslink);
- nslinks[i].innerHTML = (i + 1);
- nslinks[i].name = i;
- creaElemIn("br", root);
- var imgnode = imgboxes[i].querySelector("img");
- var imgvnode = imgboxes[i].querySelector("video"); //“动图”(实际上是mp4视频)
- // console.log('imgtest: #',i,/sinaimg.c(om|n)/.test(imgnode.src));
- if (/sinaimg.c(om|n)/.test(imgnode.src)) { // 普通大图提取
- if (/sinaimg.c(om|n)\/(orj|thumb)\d{3}/.test(imgnode.src)) {
- imgsrc = imgnode.src.replace(
- /(sinaimg\.c(om|n)\/)(orj|thumb)\d{3}/,
- "$1large"
- );
- } else if (/sinaimg.c(om|n)\/large/.test(imgnode.src)) {
- imgsrc = imgnode.src;
- }
- imgn = creaElemIn("img", bpboxes[i]);
- imgn.src = imgsrc;
- imgn.className = "big_pic";
- imgn.title = "[ " + (i + 1) + " / " + imgl + " ]";
- nslinks[i].style.backgroundImage = 'url("' + imgnode.src + '")';
- } else if (!!imgvnode) {
- if (/sinaimg.c(om|n)\/(orj|thumb)\d{3}/.test(imgvnode.poster)) { // 动图大图提取
- imgsrc = loadLargeGif
- ? imgvnode.poster.replace( // 动大图模式,使用封面的大图
- /(sinaimg\.c(om|n)\/)(orj|thumb)\d{3}/,
- "$1large"
- )
- : imgvnode.poster; // 封面模式,直接用封面
- } else if (/sinaimg.c(om|n)\/large/.test(imgvnode.poster)) { // 封面直接就是大图
- imgsrc = imgvnode.poster;
- }
- imgn = creaElemIn("img", bpboxes[i]);
- imgn.src = imgsrc;
- imgn.className = "big_pic" + ((loadLargeGif) ? "" : " big_pic_poster");
- imgn.title = "[ " + (i + 1) + " / " + imgl + " ] 点击以视频方式播放";
- imgn.onclick = function (event) {
- let pnode = event.target;
- let vnode = pnode.parentNode.getElementsByTagName("video")[0];
- pnode.style.display = "none";
- vnode.style.display = "block";
- vnode.play();
- console.log("p: ", "played");
- };
- nslinks[i].style.backgroundImage = 'url("' + imgvnode.poster + '")';
- bpboxes[i].appendChild(imgvnode); // 将动图视频附在动图大图上,点击显示
- imgvnode.className = "big_pic_v";
- imgvnode.controls = true;
- imgvnode.style.display = "none";
- imgvnode.addEventListener("ended", function (event) {
- let vnode = event.target;
- let pnode = vnode.parentNode.getElementsByTagName("img")[0];
- console.log("p: ", pnode);
- vnode.style.display = "none";
- pnode.style.display = "block";
- });
- // imgvnode.onclick = function (event) {
- // console.log("v: ", "clicked");
- // //(vnode.paused)? vnode.play() : vnode.pause();
- // };
- } else {
- j += 1;
- continue;
- }
- nslinks[i].addEventListener(
- "click",
- function (e) {
- scrollto(getTop(bpboxes[e.target.name]) - topspare + 25);
- },
- false
- );
- if (j == imgl) return;
- }
- if (j == imgl) {
- //没找到符合条件的大图,退出
- cssNode.innerHTML =
- ".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}";
- return;
- }
- imgl = bpboxes.length;
- if (!!root) root.removeChild(expbox);
-
- nclink.className = "big_pic_btn";
- nclink.innerHTML = "图片限宽";
- nclink.addEventListener(
- "click",
- function () {
- var i;
- if (_limited) {
- for (i = 0; i < imgl; i++) {
- bpboxes[i].querySelector("img").className = "big_pic";
- }
- _limited = false;
- } else {
- for (i = 0; i < imgl; i++) {
- bpboxes[i].querySelector("img").className = "big_pic_n";
- }
- _limited = true;
- }
- },
- false
- );
-
- n1link.className = "big_pic_btn";
- n1link.innerHTML = "△首个图片";
- n1link.addEventListener(
- "click",
- function () {
- scrollto(getTop(bpboxes[0]) - topspare +25);
- },
- false
- );
-
- n2link.className = "big_pic_btn";
- n2link.innerHTML = "▲上个图片";
- n2link.addEventListener(
- "click",
- function () {
- var t = document.documentElement.scrollTop;
- for (var j = imgl - 1; j >= 0; j--) {
- if (t > getTop(bpboxes[j]) + bpboxes[j].offsetHeight - topspare) {
- scrollto(getTop(bpboxes[j]) - topspare + 25);
- return;
- }
- }
- },
- false
- );
-
- n3link.className = "big_pic_btn";
- n3link.innerHTML = "▼下个图片";
- n3link.addEventListener(
- "click",
- function () {
- var t = document.documentElement.scrollTop;
- for (var j = 0; j < imgl; j++) {
- if (t < getTop(bpboxes[j]) - topspare) {
- scrollto(getTop(bpboxes[j]) - topspare + 25);
- return;
- }
- }
- },
- false
- );
-
- swmode.className = "big_pic_btn";
- swmode.innerHTML = "↔切换动图模式";
- swmode.title = "切换为" + ((loadLargeGif) ? "显示封面静图" : "显示动图大图") + "并刷新页面";
- swmode.addEventListener(
- "click",
- function () {
- loadLargeGif = !loadLargeGif;
- GM_setValue('WBimgAll', loadLargeGif);
- location.reload();
- },
- false
- );
-
- waitscroll();
-
- document.onscroll = function () {
- var t = document.documentElement.scrollTop; // 当前滚动位置(视框顶y)
- var w = window.innerHeight; // 当前视框高度
- var percentage = 1 / 4; // 视框内“注视框”距视框顶底距离(1-2*percentage 为注视框高度占比)
- var linetop = t + w * percentage - topspare; // 注视框顶位置
- var linebtm = t + w * (1 - percentage); // 注视框底位置
- var j, vh, vhmax = 0; // 检查图片序、图片在注视框内高度、注视框内最大高度
- if (getTop(bpboxes[0]) >= linebtm || getTop(bpboxes[imgl - 1]) + bpboxes[imgl - 1].offsetHeight <= linetop) {
- cur = -1; // 若首图在注视框底之下或末图在注视框顶之上,则无当前图
- } else {
- for (j = imgl - 1; j >= 0; j--) { // 从底部检查各图片
- let ti = getTop(bpboxes[j]), hi = bpboxes[j].offsetHeight; // 检查图片位置、检查图片高度
- if (ti < linebtm && (ti + hi) > linetop) { // 若图片顶端在注视框底之上、底端在注视框顶之下
- vh = Math.min(linebtm, ti + hi) - Math.max(linetop, ti); // 计算注视框内高度
- if (vh >= vhmax) { // 当检查图片拥有更大的注视框内高度,则其为“当前图片”(等高则更前)
- vhmax = vh;
- cur = j;
- }
- }
- }
- }
- if (cur !== -1) {
- for (j = imgl - 1; j >= 0; j--) {
- if (j !== cur) {
- nslinks[j].classList.remove("curr");
- } else {
- nslinks[j].classList.add("curr");
- }
- }
- } else {
- for (j = imgl - 1; j >= 0; j--) {
- if (j !== cur) {
- nslinks[j].classList.remove("curr");
- }
- }
- }
- };
- }
-
- function waitscroll() {
- //等待页面完全载入再滚动
- var list_ul = document.querySelector("div.list_ul"); //↓等待评论框架载入,如果评论框架就位就等待评论区或无评论提示载入,再视滚动位置判断
- if (
- !list_ul ||
- !list_ul.getElementsByTagName("div")[0] ||
- !document.querySelector("div.tips_rederror") ||
- document.documentElement.scrollTop < topheight + 70
- ) {
- setTimeout(waitscroll, 300); //console.log("wait");
- return;
- } else {
- scrollto(topheight); //console.log("scroll");
- }
- }
-
- function scrollto(pos) {
- //滚动
- document.documentElement.scrollTop = pos;
- }
-
- // Create an element
- function creaElemIn(tagname, destin) {
- var theElem = destin.appendChild(document.createElement(tagname));
- return theElem;
- }
- // Get the first element by xpath
- function getElem(xpath) {
- return document
- .evaluate(
- xpath,
- document,
- null,
- XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
- null
- )
- .snapshotItem(0);
- }
- // Get the absolute top of an element
- function getTop(e) {
- var offset = e.offsetTop;
- if (e.offsetParent != null) offset += getTop(e.offsetParent);
- return offset;
- }
-
- })();