// ==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;
}
})();