您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Shift+H:オンオフ切替 y:ホバー中の画像をyandexで画像検索 a:twitterで画像をトリミングさせない
当前为
// ==UserScript== // @name 画像のホバーで拡大 // @description Shift+H:オンオフ切替 y:ホバー中の画像をyandexで画像検索 a:twitterで画像をトリミングさせない // @version 0.1.8 // @run-at document-idle // @match *://*/* // @noframes // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_download // @exclude *://*.5ch.net/* // @exclude *://jbbs.shitaraba.net/* // @namespace http://greasyfork.icu/users/181558 // ==/UserScript== (function() { var keyFunc = [] const hoverTimeDefault = 3; // 拡大するタイミング 0:オフ 1:画像に乗った瞬間 2-:画像に乗せてn/60秒静止したら const defaultDelay = 3; // hoverTimeDefaultが0で手動オン時に拡大するタイミング 1:画像に乗った瞬間 2-:画像に乗せてn/60秒静止したら const marginH = 100; // 元絵と拡大画像の横の余白px const CONFIRM_FOR_Y = 1; // 1:yキーでyandex検索をする時URLの確認を求める const KEY_SELECT_DELAY = "Shift+H"; // 設定キー const ZMARGIN = 1; const POPUP_Z_INDEX = 2147483647 - ZMARGIN; // ポップアップ画像がどくらい手前に来るか const FORCE_USE_HALF_WIDTH = 0; // 1:ホバーズームで必ず画面の横半分のサイズ const enablePanel = 1; // 1:パネル表示を有効 const marginPe = 8; const verbose = 0; // 1:debug String.prototype.match0 = function(re) { let tmp = this.match(re); if (!tmp) { return null } else if (tmp.length > 1) { return tmp[1] } else return tmp[0] } // gフラグ不可 var domain = new URL(location.href).hostname; var hovertime = pref(domain + " : delay") || hoverTimeDefault; const minWidth = location.href.match(/twitter/) ? 1000 : (window.innerWidth / 2); const minHeight = location.href.match(/twitter/) ? 1000 : (window.innerHeight / 2); var mousex = 0; var mousey = 0; var lastEle = ""; var hovertimer = 0; var poppedUrl = ""; var yandexUrl = ""; if (lh("//twitter.com/")) { var zflag = pref("zflag") || 0; setTimeout(() => setsize(zflag), 999) } function setsize(z) { GM_addStyle(`div{ background-size:${['cover','contain'][z]} !important;}`) } document.addEventListener("keypress", e => { if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.isContentEditable) return; var key = (e.shiftKey ? "Shift+" : "") + (e.altKey ? "Alt+" : "") + (e.ctrlKey ? "Ctrl+" : "") + e.key; keyFunc.forEach(v => { if (v.key === key) { v.func(e) } }) if (key === "y" && poppedUrl) { // y::ホバー中の画像をyandex画像検索で検索 yandexUrl = poppedUrl.match(/\;base64\,/i) ? null : "https://yandex.com/images/search?rpt=imageview&url=" + poppedUrl; if (!CONFIRM_FOR_Y || window.confirm(yandexUrl + "\n\nを開きます。よろしいですか?")) window.open(yandexUrl); return false; } if (key === "a" && lh("//twitter.com")) { // a::twitterで画像をトリミングさせないオンオフ zflag = zflag ^ 1; setsize(zflag) pref("zflag", zflag) return false; } if (key === KEY_SELECT_DELAY) { // Shift+H::ホバーの設定 elegeta('//img[@class="ignoreMe hzP"]').forEach(e => e.remove()); // let ret = proInput(domain + `\n\nのホバーズームの設定をしてください\n\n-1:オフ\n0:デフォルト(${hoverTimeDefault})\n1:画像に乗った瞬間\n2-:画像に乗せて数値/60秒静止したら\n空欄:設定削除(${hoverTimeDefault})\n\n`, pref(domain + " : delay") || defaultDelay); let ret = hovertime > 0 ? -1 : defaultDelay; if (ret === "") { pref(domain + " : delay", ""); hovertime = hoverTimeDefault; } else { if (ret !== null) { hovertime = ret || hoverTimeDefault; pref(domain + " : delay", hovertime); popup(`${domain}<br>${KEY_SELECT_DELAY}:ホバーズームを${hovertime>0?"有効":"無効"}にしました${hovertime>0?"("+hovertime+"/60秒)":""}`, hovertime > 0 ? "#6080ff" : "#808080") } } } }); var input_key_buffer = new Array(); document.addEventListener('keyup', function(e) { if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.isContentEditable) return; input_key_buffer[e.keyCode] = false; }, false); document.addEventListener('blur', function(e) { input_key_buffer.length = 0; }, false); document.addEventListener('keydown', function(e) { if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.isContentEditable) return; input_key_buffer[e.keyCode] = true; }, false); document.addEventListener("mousemove", function(e) { mousex = e.clientX; mousey = e.clientY; hovertimer = 0; }, false); document.addEventListener("wheel", function(e) { hovertimer = 0; }, false); // setInterval(hzOnInt, 16.667); hzOnInt() function hzOnInt() { if (!(hovertime < 1)) { hovertimer++; let ele = document.elementFromPoint(mousex, mousey); if (lastEle !== ele) { hovertimer = 0; if (poppedUrl) { /* elegeta('//img[contains(@class,"ignoreMe hzP")]').forEach(e => e.remove()); elegeta('//span[contains(@class,"ignoreMe hzP")]').forEach(e => e.remove()); */ document?.querySelectorAll('.ignoreMe.hzP')?.forEach(e => e.remove()); poppedUrl = ""; } } if (ele && hovertimer >= hovertime && poppedUrl == "" && (ele.clientWidth < minWidth || ele.clientHeight < minHeight)) if ((ele.tagName === "IMG") // || (ele.classList.contains("Thumbnail-image") && ele.style.backgroundImage)){//ele.style.match0(/^background-image:\s?url/) ) ) { || (ele?.style?.backgroundImage?.match0(/^url\(/))) { if (ele?.dataset?.zoomonhover != "disable") { poppedUrl = pe(ele); // yandexUrl = poppedUrl.match(/\;base64\,/i) ? null : "https://yandex.com/images/search?rpt=imageview&url=" + poppedUrl; } } lastEle = ele; } setTimeout(hzOnInt, 17); } function pe(a) { if (/magnifierLens/.test(a.id)) return null; // amazon拡大鏡の水色のドット // if(a?.dataset?.zoomonhover=="disable")return null let imgAspect = a.naturalWidth / a.naturalHeight; // svg等だとNaN 要.onload let clientAspect = window.innerWidth / 2 / window.innerHeight; // 動画 if (a?.dataset?.srcvideo || (a.parentNode.tagName == "A" && a.parentNode.href.match(/.mp4(\?.+)*$|.webm(\?.+)*$/i))) { var ext = (a?.dataset?.srcvideo || a.parentNode.href).match(/.mp4(\?.+)*$|.webm(\?.+)*$/i)[0]; //console.log(ext,a.parentNode.href) var src = a?.dataset?.srcvideo || a.parentNode.href; if (enablePanel) { var ve = document.createElement("video") var panel = document.createElement("span"); panel.referrerpolicy = "no-referrer"; // 無効 panel.className = "ignoreMe hzP"; panel.appendChild(ve) panel.src = src panel.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 750, fill: 'forwards' }); // ve.outerHTML = `<video className="ignoreMe hzP" id="hzPv" controls autoplay loop referrerpolicy="no-referrer" width="100%" height="100%"><source referrerpolicy="no-referrer" src="${a.parentNode.href}" type="video/mp4">Sorry, your browser doesn't support embedded videos.</video>`; ve.outerHTML = `<video className="ignoreMe hzP" id="hzPv" controls autoplay loop referrerpolicy="no-referrer" width="100%" height="100%"><source referrerpolicy="no-referrer" src="${src}" type="video/mp4">Sorry, your browser doesn't support embedded videos.</video>`; panel.maxWidth = "18%"; } } else // if(a.classList.contains("Thumbnail-image") && a.style.backgroundImage){ if (a.style.backgroundImage?.match0(/^url\(/)) { // bacgground-image式の画像 var src = (a.style.backgroundImage.match0(/url\(\"([^"]+)/)) if (enablePanel) { var panel = document.createElement("img"); panel.referrerpolicy = "no-referrer"; panel.className = "ignoreMe hzP"; panel.src = src } } else { // 画像 // var src = a.dataset.src||a.src var src = a.src if (a.parentNode && a.parentNode.tagName == "A" && a.parentNode.href.match(/.png$|.jpg$|.jpeg$|.gif$|.bmp$|.webp$/i) && /\.wikipedia\./.test(location.href) == false) { src = a.parentNode.href; } else if (a.parentNode && a.parentNode.parentNode && a.parentNode.parentNode.tagName == "A" && a.parentNode.parentNode.href.match(/.png$|.jpg$|.jpeg$|.gif$|.bmp$|.webp$/i)) { src = a.parentNode.parentNode.href; } if (a.srcset) { var srcWiki = a.srcset.match(/\/\/\S+/g); if (srcWiki.length) { srcWiki = srcWiki[srcWiki.length - 1].replace(/\/\d+px-.*$/i, "").replace(/\/thumb\//i, "/"); } // alert(srcWiki)} } //if(src.match0(/.+?\.2chan\.net\/b\/thumb\/.+?s\..+?/)){src=src.replace(/(.+?\.2chan\.net\/b\/)(?:cat|thumb)(\/.+?)s(\..+?)/,"$1src$2$3")} // 拡張子が分からない //if(/https:\/\/i\.pximg\.net\/[^/]+\/[^/]+\/[^/]+\/img\/.+/.test(panel.src)) {panel.src=panel.src.replace(/(https:\/\/i\.pximg\.net\/)[^/]+\/[^/]+\/([^/]+\/img\/.+)/,"$1$2").replace(/custom-thumb/,"img-master").replace(/_custom/,"_master");} // pixiv if (/^https?:\/\/.+\.2chan\.net\/b\/cat\//.test(src)) { src = src.replace(/^(https?:\/\/.+\.2chan\.net\/b\/)cat\//, "$1thumb/"); } // futapo if (src.match0(/\?w=\d+\&h=\d+$/)) src = src.replace(/\?w=\d+\&h=\d+$/, ""); src = srcWiki || src.replace(/(https:\/\/pbs\.twimg\.com\/.*\?format=.+\&name=).+/, "$1orig"); if (enablePanel) { var panel = document.createElement("img"); panel.referrerpolicy = "no-referrer"; panel.className = "ignoreMe hzP"; panel.src = src } } if (enablePanel) { let peStyle = 'margin:2px; border-radius:3px; color:#ffffff; box-shadow:3px 3px 8px #0008; border:2px solid #fff;'; let boxPos = (mousey < (window.innerHeight / 2) ? "bottom:0px;" : "top:0px;") + ((mousex < document.documentElement.clientWidth / 2) ? "right:0px; " : "left:0px;"); panel.className = "ignoreMe hzP"; let aw = (mousex < document.documentElement.clientWidth / 2) ? (document.documentElement.clientWidth - (a.getBoundingClientRect()).right) : (a.getBoundingClientRect().left); if (imgAspect && (((aw - marginH) / imgAspect) <= window.innerHeight && (aw - marginH - marginPe) > a.width * 2.5)) { panel.setAttribute("style", `all:initial;float:none; width:${aw-marginH-marginPe}px; height:${(aw-marginH)/imgAspect-marginPe}px;${boxPos} z-index:${POPUP_Z_INDEX}; position:fixed; ${peStyle}`); // 元絵の左右にくっつき最大 if (verbose) popup(`nx:${a.naturalWidth} ny:${a.naturalHeight} a:${Math.round(imgAspect*100)/100} くっつき`) } else if (imgAspect && ((window.innerHeight * imgAspect - marginPe) < aw - marginH)) { if (imgAspect < 0.46 && !ve) { // 48%+スクロール panel.setAttribute("style", `all:initial;float:none; width:${window.innerWidth*0.48-marginPe}px; height:${window.innerWidth*0.48/imgAspect-marginPe}px; ${boxPos} top:0px; z-index:${POPUP_Z_INDEX}; position:fixed; ${peStyle}`); // 48%+スクロール if (window.innerWidth * 0.48 / imgAspect - marginPe > window.innerHeight) setTimeout(() => { panel.animate([{ top: '0px' }, { top: `-${window.innerWidth*0.48/imgAspect-marginPe-window.innerHeight+marginPe}px` }], { duration: (window.innerWidth * 0.48 / imgAspect - marginPe - window.innerHeight + marginPe) * 4, fill: 'forwards' }); }, 1000) if (verbose) popup(`nx:${a.naturalWidth} ny:${a.naturalHeight} a:${Math.round(imgAspect*100)/100} width:${window.innerWidth*0.48-marginPe}px; height:${window.innerWidth*0.48/imgAspect-marginPe}px; 48%+スクロール`) } else { panel.setAttribute("style", `all:initial;float:none; width:${(window.innerHeight)*imgAspect-marginPe}px; height:${((window.innerHeight))-marginPe}px;${boxPos} z-index:${POPUP_Z_INDEX}; position:fixed; ${peStyle}`); // 縦目いっぱい if (verbose) popup(`nx:${a.naturalWidth} ny:${a.naturalHeight} a:${Math.round(imgAspect*100)/100} 縦目いっぱい`) } } else if (!imgAspect || window.innerWidth * 0.48 / imgAspect - marginPe <= window.innerHeight) { panel.setAttribute("style", `all:initial;float:none; width:${window.innerWidth*0.48-marginPe}px; height:${window.innerWidth*0.48/imgAspect-marginPe}px; ${boxPos} z-index:${POPUP_Z_INDEX}; position:fixed; ${peStyle}`); // 横48% if (verbose) popup(`nx:${a.naturalWidth} ny:${a.naturalHeight} a:${Math.round(imgAspect*100)/100} width:${window.innerWidth*0.48-marginPe}px; height:${window.innerWidth*0.48/imgAspect-marginPe}px; 48%`) } else { panel.setAttribute("style", `all:initial;float:none; width:${(window.innerHeight)*imgAspect-marginPe}px; height:${((window.innerHeight))-marginPe}px;${boxPos} z-index:${POPUP_Z_INDEX}; position:fixed; ${peStyle}`); // 縦目いっぱい if (verbose) popup(`nx:${a.naturalWidth} ny:${a.naturalHeight} a:${Math.round(imgAspect*100)/100} 縦目いっぱい2`) } if (a.clientWidth < document.documentElement.clientWidth * 0.48) document.body.appendChild(panel); } return src; } function elegeta(xpath, node = document) { if (!xpath || !node) return []; let flag if (!/^\.?\//.test(xpath)) return /:inscreen$/.test(xpath) ? [...node.querySelectorAll(xpath.replace(/:inscreen$/, ""))].filter(e => { var eler = e.getBoundingClientRect(); return (eler.top > 0 && eler.left > 0 && eler.left < document.documentElement.clientWidth && eler.top < document.documentElement.clientHeight) }) : /:visible$/.test(xpath) ? [...node.querySelectorAll(xpath.replace(/:visible$/, ""))].filter(e => e.offsetHeight) : [...node.querySelectorAll(xpath)] try { var array = []; var ele = document.evaluate("." + xpath.replace(/:visible$/, ""), node, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); let l = ele.snapshotLength; for (var i = 0; i < l; i++) array[i] = ele.snapshotItem(i); return /:visible$/.test(xpath) ? array.filter(e => e.offsetHeight) : array; } catch (e) { popup3(e + "\n" + xpath + "\n" + JSON.stringify(node), 1); return []; } } function eleget0(xpath, node = document) { if (!xpath || !node) return null; if (!/^\.?\//.test(xpath)) return /:visible$/.test(xpath) ? [...node.querySelectorAll(xpath.replace(/:visible$/, ""))].filter(e => e.offsetHeight)[0] ?? null : node.querySelector(xpath.replace(/:visible$/, "")); try { var ele = document.evaluate("." + xpath.replace(/:visible$/, ""), node, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); return ele.snapshotLength > 0 ? ele.snapshotItem(0) : null; } catch (e) { alert(e + "\n" + xpath + "\n" + JSON.stringify(node)); return null; } } function pref(name, store = null) { // prefs(name,data)で書き込み(数値でも文字列でも配列でもオブジェクトでも可)、prefs(name)で読み出し if (store === null) { // 読み出し let data = GM_getValue(name) || GM_getValue(name); if (data == undefined) return null; // 値がない if (data.substring(0, 1) === "[" && data.substring(data.length - 1) === "]") { // 配列なのでJSONで返す try { return JSON.parse(data || '[]'); } catch (e) { alert("データベースがバグってるのでクリアします\n" + e); pref(name, []); return; } } else return data; } if (store === "" || store === []) { // 書き込み、削除 GM_deleteValue(name); return; } else if (typeof store === "string") { // 書き込み、文字列 GM_setValue(name, store); return store; } else { // 書き込み、配列 try { GM_setValue(name, JSON.stringify(store)); } catch (e) { alert("データベースがバグってるのでクリアします\n" + e); pref(name, ""); } return store; } } function prefRestrict(name, type) { let data = pref(name); if (!data) return data; if (type === "array") { if (typeof data === "object") { return data; } else { alert("データベースの形式に誤りがある(配列/オブジェクトでない)ためクリアします\n"); pref(name, ""); return []; } } return data; } function proInput(prom, defaultval, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) { let ret = window.prompt(prom, defaultval) if (ret === null) return null; if (ret === "") return ""; return Math.min(Math.max(Number(ret.replace(/[A-Za-z0-9.-]/g, function(s) { return String.fromCharCode(s.charCodeAt(0) - 65248); }).replace(/[^-^0-9^\.]/g, "")), min), max); } function popup(text, color = "#6080ff") { text = String(text); var e = document.getElementById("hzbox"); if (e) { e.remove(); } var e = document.body.appendChild(document.createElement("span")); e.innerHTML = `<span id="hzbox" style="all:initial; position: fixed; right:1em; top: 1em; z-index:${POPUP_Z_INDEX+ZMARGIN}; opacity:1; font-size:14px; font-weight:bold; margin:0px 1px; text-decoration:none !important; text-align:left; padding:1px 6px 1px 6px; border-radius:12px; background-color:${color }; color:white; white-space: nowrap;" onclick=\'var a = document.createElement(\"textarea\"); a.value = \"${ text.replace(/<br>/gm, "\\n") }\"; document.body.appendChild(a); a.select(); document.execCommand(\"copy\"); a.parentElement.removeChild(a);\'">${ text }</span>`; setTimeout((function(e) { return function() { e.remove(); } })(e), 5000); } function lh(re) { let tmp = location.href.match(re); if (!tmp) { return null } else if (tmp.length > 1) { return tmp[1] } else return tmp[0] } // gフラグ不可 })();