您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
鼠标指向链接标识图标预览链接网页
当前为
// ==UserScript== // @name 链接预览 // @name:zh-cn 链接预览 // @name:en Link Previewer // @namespace http://greasyfork.icu/zh-CN/users/1073-hzhbest // @version 1.2 // @description 鼠标指向链接标识图标预览链接网页 // @description:zh-cn 鼠标指向链接标识图标预览链接网页 // @description:en Hovering to preview a link // @author hzhbest // @match *://*/* // @grant none // @license MIT // ==/UserScript== (function () { 'use strict'; // --------自定义区-------- // const minHgap = 20, minVgap = 10; // 预览窗距鼠标位置的右、下最大距离:像素 var winWidth = 700, winHeight = 550; // 预览窗宽、高:像素 const scale = 0.9; // 预览窗内页面放大率:(0~1] const animationtime = 0.5; // 动画时长:秒 const iconsize = 20; // 图标放大后大小:像素 const icontrpr = 0.7; // 图标放大后不透明度:(0~1) const pre = "░░░░░░ "; // 移动手柄显示:字符串 const preID = "__link__prev_win" // 预览窗id // --------自定义区结束--------// const ixonimg = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAoUlEQVQ4y8XSyw3CMBAE0AekkHTBBZGkCa40QA9AOVADEkGiEJfCxZEsk+8F5mLZs7Mzay3/xmpm3Tm7v9DCeqHhDhdU3UORkHVKJAi4osEJj5RME1SxiZ64De444J2SRVbcRjdZslsUP7Efa6BH3DkHHHOD9UxxG8VlXjTUoExit2MRh0YI2MZzFGMjTIr7EtQTf/I1zmbBWoe4E7OS/Q4fA1sbIN+Dzp4AAAAASUVORK5CYIIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="; const inonimg = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAATr4AAE6+AGeOBvEAAAA3klEQVQ4y83SPUpDURAF4M8YooUiIi7BQBaQ2lqirZjnVrIFCwsLDbbZgLoAO8FC7EJcgNgZUpvYTOByee/513hguDB3zpm5cy5/xOovOI0qgUZJ5FjDBbbxnF5s4hHjLPYz8jVmOFwmm0n3PdzhJXIreM06H6OP23y0LbyjVzJ2C8O8c51AGwOsB/kqyEd1m00FephiF5dfkZs1Vp0H8RQ3kS/iHJV6mmADJziLRe4kAkXlpwgsMI8Y4AEHP3nCPTohtMTbdwUKdCtq5+HQpEzgA09R0K5xa5p8tH+CT7aEK2vlnm2YAAAAAElFTkSuQmCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="; const loadimg = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAArVQTFRFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////9ykBcAAAAOV0Uk5TABVarN/1/KoWDW3G9sdpDhyj+fqkHbW2C6GdDGZoG9DTHmr9/nIGsboKF9beHyno7jMw7PM6CBQZKu80CTyCuNLZuYo+BxggAkOv8K1PBa5s6vFrA294Z/RgASLU2CVB4elSepyUYhO/ZLJcX3UvwMErsKUh++B3JBB+ETnylQSizeWgRfiL7TFVyBIu6w9ehYPV5sLkLCdxhKi7tIGNbnlQc8XddEw497yfRllLyViAiZbPmtqYY3Ce4+Iyt46SYafbTdEtGss9f0BONUnDVHx7P+dCk8pXUSN9hkdlN4jE1zvMVjfQwZEAAAABYktHRObBbFoFAAAACXBIWXMAAAxRAAAMUQFArTLzAAAFV0lEQVRo3mNgIBYwMjGzsLKxsrAzcRCthwTAycXN8xQCeHj5+KluvoCg0FMEEBYRpbL5omJPUYG4AFXNl5B8ig6kpKlpgYwQhgVCslQ0X07+KSZQUKSeBUrKWCxQUaWa+WrqT7EBDU1qWaCljdUCHV1qWaCnj9UCA0NqWWBkjNUCE1NUZWbmFuZmZFlgid0HVtZIamxs7ewdHB2cnF1cSbfADUccuMNVeHh6ecMCzsfXj1QL/PyxWuBkA1OgFhCIJB4UHEKqDaFYLQiDy4dHoMZ+ZBSJFkTHYDE/Ng4mHZ+AJpWYhMewKKPklNQ0tNKYTxjDfOEAmGR6BoakPO5ixC8T5Bxl+XgUUf4sDDOY4XVONqbtyjm4zA/JNYEoibFGEc/LRzOioBAmZVaEJfykPHBYYA1P8sVqKBIlzKVI+tl8ohEyZVgscGDEYUE5XElCBapMpV0iIhKrqhESNbVYLNDXw2FBHVwJekHAUG8Y3NBY1lTW2BxsWI8k3tKKxQIraxwWtMGVtHdgytZXK1YoVqNlo3geLBYYG+GwoBNeN3Z1MxAHenqxWMCCqyjvY4eFUD+R5jNUd2GxQNwGl/IScRVwNppAfIk1EYsFYbiVa02YFDh5iiwn0eYz5E3FMN/ABY/6EK1p00lqGUbNQE9HbDNJLrHxAk0RNAtmVVNuKAqomI1i/hwBKpsPbBrPnQw3PnCeO+UGYgAPW0kWUBYSbmo2rafcOGzAL9p3/oL5C6erUW7UKBgFQODB6WbRR3Lri2iguEhwcWxsl0j5dFLbX0QBNSYHaH9IZUkkDfKcx1KkZmTQAmhzvnJZVZvqcvLa9qgghMsKudhb4SwBFIyKX7kCVEmsokIhtRqtr9K6Bii4tgnK8zGn1HxOcYzKuY8heh2Mo5JKRu8EBaxlRbfAZD3DBkQn2MqWQgs2Ylb/IgyLkXjlFFqwCdOCzQzIvYc6Ci3YgmlBAsNWJN48Ci3YhmnBEgak5r3KdgotqMO0YApDkgGcI0/p4MAODPNV7Bhcd8Jz9noKzWco3IVuwe49DAxxeyEJlSeM4rLJYx+6BftBfSmOAwcdDq3bf9iGUvOBDSQnVPOPHIWI+5kf6/OgzGgomH4c2XzHE1QxFAXUdKnAze9aTn3zGRhEgwtMQHaYcIdFU24aVlDtEn5yQ8ApajexR8EoGAV+caf5QvvPEDOpUGl41rOCxJ5W1LQtu4SBtYuBxnpCI+YWYeeshHh2e50npa8unasDK994duKf3dFbCS0LvS8QXztEXUQeFpxzDI9SfsQYb2s50RXEpcsolcw2PK3o3FKEOuMrRJpfrYFai0Wcxqn0GMoI70wiLVi2Aq0evopT6SmUMei9RDaFJ6BX9Ndw1gTX2ZDVNRJXY4TMQregKQ6X2hulyOq6iBuW8sMYdg48ikvtHpT+yUHiOqIexegW7LqJS60EynxWMIZ8FH+JZQk/euf0AroF53B73RNpDFS+BF1W9OLihMTd3LfQJFyC0CyYgMe7t+Hdnaln0eUOb4ZIqky6jhJ4EmiRYHIHT4BWqi4BK1KefQo9JDIRvrO6iyJ5bwmy+aX38SbvKL3bDx4qqCthzKrvYUFOiI9Q5GSQ8o9ySh8DfhDF6caIWVr77UQJBnaU8sZPBt5sF64js71lhDpZ116DGj97bj9uFxJmPSTVSe5sf6QKigVPudD9nd5x9vQlRfLHcJLRkuJ9sk3CAS6iWbCR2hakoQXRfGpbcKYdxfwgqnddzFBH2NklqG0BQ4cOkvks1pQbiAGCWeHms2bSwHwG185zkNaJ8LknlI4r4QBu5Y+D2IIe57qRpAsA7kV3j3RnhzoAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTgtMDUtMjhUMTM6NDI6MTQrMDI6MDBcmjn8AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE4LTA1LTI4VDEzOjQyOjE0KzAyOjAwLceBQAAAAEZ0RVh0c29mdHdhcmUASW1hZ2VNYWdpY2sgNi43LjgtOSAyMDE2LTA2LTE2IFExNiBodHRwOi8vd3d3LmltYWdlbWFnaWNrLm9yZ+a/NLYAAAAYdEVYdFRodW1iOjpEb2N1bWVudDo6UGFnZXMAMaf/uy8AAAAYdEVYdFRodW1iOjpJbWFnZTo6aGVpZ2h0ADUxMsDQUFEAAAAXdEVYdFRodW1iOjpJbWFnZTo6V2lkdGgANTEyHHwD3AAAABl0RVh0VGh1bWI6Ok1pbWV0eXBlAGltYWdlL3BuZz+yVk4AAAAXdEVYdFRodW1iOjpNVGltZQAxNTI3NTA3NzM0WBVSAAAAABN0RVh0VGh1bWI6OlNpemUAMTEuOEtCQpyFMfMAAABFdEVYdFRodW1iOjpVUkkAZmlsZTovLy4vdXBsb2Fkcy81Ni9IUkNEWEdQLzE0ODkvbG9hZGluZ2NpcmNsZXNfMTAyNjEyLnBuZxRGwnYAAAAASUVORK5CYIIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; const domainregex = /(?<=:\/\/)[^\/]+/; const id = "__link__prev"; const css = ` /* 链接样式 */ a.___prevlink>img.___previcon { width: 16px !important; height: 16px !important; opacity: 0%; transition: opacity 0.5s ease-out, background 0s; position: absolute; display: inline-block !important; margin: 0 !important; } a.___prevlink.__pr { position: relative; } *:hover>a.___prevlink>img.___previcon { opacity: 30%; } a.___prevlink:hover>img.___previcon { opacity: ${icontrpr}; background: white; border: 1px solid #8d8d8db1; transition: opacity 0.5s linear; z-index: 10008; transform: scale(${iconsize / 16}); } a.___prevlink>img.___previcon:hover { background: #3e3ed3 !important; transition: background 1s !important; } a.__link__preved { outline: 3px solid #3e3ed3; } /* 预览窗样式 */ div#${preID} { opacity: 0; position: absolute; z-index: 10009; box-shadow: 1px 1px 7px 1px #717171; padding: 0; margin: 0; background-color: white; transition: ${animationtime}s ease; } div#${preID}.__close { transition: 0s !important; display: none; } div#${preID}.__loading { background: url(${loadimg}) no-repeat center center; background-color: #e7e7e7; } div#${preID}.__link__visible { opacity: 1; transition: 0.2s !important; } div#${preID}.visible .__link__prev_ifr { border: none; transform: scale(${scale}); max-width: unset !important; width: calc(100% / ${scale}); max-height: unset !important; height: calc(100% / ${scale}); } div#${preID}.__onmove, div#${preID}.__onsize{ transition: 0s !important; } div#${preID}.__onmove { opacity: 0.7; } /* 关闭按钮样式 */ @keyframes rotating_button { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } div#${preID}>.__link__clos_btn { position: absolute; top: -10px; right: -10px; z-index: 10010; line-height: 24px; width: 24px; height: 24px; color: white; font-family: Consolas; font-size: 16px; text-align: center; background: #df2020; border: 1px solid black; border-radius: 50%; box-shadow: 1px 1px 5px #333; cursor: default; padding: 0 !important; margin: 0; } div#${preID}>.__link__clos_btn.__loading { animation: 3s linear 0s infinite rotating_button; background: #d76565; } div#${preID}>.__link__clos_btn.__loading:hover { animation: none; background: #df2020; } div#${preID}>.__link__clos_btn:hover { outline: 3px solid #be3737a2; } div#${preID}>.__link__clos_btn.__close { display: none; } /* 拖动手柄样式 */ div#${preID}>div.__link__prev_mv { position: absolute; top: -5px; left: 0px; z-index: 10010; height: 6px; width: 30px; border: 1px solid #242424; background: #3e3e3e; cursor: move; border-radius: 3px; overflow: hidden; max-width: ${winWidth}px; font-size: 14px !important; color: #d7d7d7; line-height: 20px; } div#${preID}>div.__link__prev_mv>* { display: inline-block; width: fit-content; } div#${preID}>div.__link__prev_mv:hover { color: #e0a52e; height: 20px; top: -20px; width: fit-content; } div#${preID}.__onmove>div.__link__prev_mv { background: #6f6122; height: 50px; top: -20px; width: fit-content; } div#${preID} .__link__prev_ttl { font-size: 14px !important; font-family: Arial; white-space: nowrap; margin: 0 3px; } div#${preID}>.__link__prev_rs { height: 4px; width: 4px; border: 1px solid #616161; color: #9a9276; font-size: 13px; position: absolute; right: 0; bottom: 0; z-index: 10011; background: #3e3e3e67; transition: 0.3s ease-out; font-size: 10px; line-height: 10px; overflow: hidden; cursor: nw-resize; } div#${preID}:hover>.__link__prev_rs { background: #3e3e3e; height: 12px; width: 12px; } div#${preID}>.__link__prev_rs:hover { border-color: #2c96e2af; height: 18px; width: 18px; } div#${preID}.__onsize>.__link__prev_rs { height: 40px; width: 60px; transition: 0s; color: #e0a52e } `; addCSS(css, id); // 添加的style节点添加id,用于判断是否需重添加 var previewwin, pre_ir, timer, linkprev, closebtn, movehand, titlebox, ondrag, resizehand, rsdrag; makeprevwin(); var site = location.host; document.addEventListener('mouseover', (evt) => { // 检查鼠标下的节点,查找链接添加图标 const t = evt.target; if (t.tagName == "A" && ispagelink(t)) { addIconTo([t]); } else { var links = getLinksInThreeLayer(t); addIconTo(links); } }); setTimeout(function () { // 延时设置监视器,若标题变化则重新加载 var watch = document.querySelector('title'); new (window.MutationObserver || window.WebKitMutationObserver)(function (mutations) { // console.log('标题变了', document.title); if (!document.querySelector("#" + id)) { addCSS(css, id); } if (!document.querySelector("#" + preID)) { makeprevwin(); } site = location.host; }).observe(watch, { childList: true, subtree: true, characterData: true }); }, 1000); function addIconTo(links) { // 往链接上添加图标;输入:链接的数组 var lnkl = links.length; var exl = 0; // console.log(lnkl); for (let i = 0; i < lnkl; i++) { const lnk = links[i]; if (lnk.classList.contains("___prevlink")) { // 跳过已处理的链接 continue; } lnk.classList.add("___prevlink"); if (window.getComputedStyle(lnk).position == "static") { // 若链接本身无position设置则添加定位样式 lnk.classList.add("__pr"); } var lnkposit = getTrueSize(lnk); // 获取链接实占空间 var textWidth = mixStringLength(lnk.textContent ,parseInt(window.getComputedStyle(lnk).fontSize)); textWidth = Math.min(lnkposit.w, textWidth); // 以文本宽度和链接宽度中较少者为右边界 var img; img = creaElemIn('img', lnk); img.className = '___previcon'; img.style.bottom = '0.1em'; var adj = textWidth + 4; // 右边界右4像素;如果被父节点遮挡或自身隐藏 if (lnkposit.r < (4 + iconsize) || window.getComputedStyle(lnk).overflow !== "visible") { adj = Math.min(adj, lnkposit.w - 5 - iconsize); // 则避开遮挡 } img.style.left = adj + "px"; if (domainregex.exec(lnk.href)[0] !== site) { // 站内还是站外链接 img.src = ixonimg; exl += 1; } else { img.src = inonimg; } img.addEventListener('mouseover', (evt) => { // 鼠标悬停图标上的动作 //clearTimeout(timer); setTimeout(() => { if (previewwin.classList.contains("__close")) { // 若预览窗关闭状态则移动到鼠标下 setWinPosit(evt.x, evt.y); } }, 1000); timer = setTimeout(previewlink, 1000, evt); // 一秒后开启预览窗 }); img.addEventListener('mouseleave', () => { // 鼠标离开鼠标则清除计时 clearTimeout(timer); }); } //console.log("external link count:" + exl); window.addEventListener('mousedown', (e) => { // 点击页面的动作 var target = e.target; if (isPrevVisual() && !previewwin.contains(target)) { // 若预览窗开启且点击位置不在预览窗内则隐藏预览窗 hidepreview(e); } }, true); } function makeprevwin() { // 生成预览窗 previewwin = creaElemIn('div', document.body); previewwin.id = preID; previewwin.style.width = '100px'; // 显示前预览窗大小,显示时形成放大效果 previewwin.style.height = '100px'; previewwin.classList.add("__close"); // 初始状态关闭 movehand = creaElemIn('div', previewwin); // 移动手柄 movehand.classList.add("__link__prev_mv"); movehand.innerHTML = pre; resizehand = creaElemIn('div', previewwin); // 调整大小手柄 resizehand.className = "__link__prev_rs"; titlebox = creaElemIn('div', movehand); // 标题栏 titlebox.className = "__link__prev_ttl"; pre_ir = creaElemIn('iframe', previewwin); // 预览容器iframe pre_ir.className = "__link__prev_ifr"; pre_ir.style.border = 0; closebtn = creaElemIn('div', previewwin); // 关闭按钮 closebtn.classList.add("__link__clos_btn"); closebtn.innerHTML = "✖"; closebtn.addEventListener('click', hidepreview); ondrag = endrag(previewwin, { x: 'left', y: 'top' }, movehand); // 绑定移动预览窗对象 ondrag.hook('__drag_begin', () => { // 绑定移动开始、结束状态样式 previewwin.classList.add("__onmove"); }); ondrag.hook('__drag_end', () => { previewwin.classList.remove("__onmove"); }); rsdrag = endrag(previewwin, { x: 'width', y: 'height' }, resizehand); // 绑定调整预览窗大小对象 rsdrag.hook('__dragging', () => { // 调整中更新iframe大小,记录预览窗大小 if (!!rsdrag.position) { // 未开始拖动前该对象不存在,判断避免编译出错 winWidth = rsdrag.position._x; winHeight = rsdrag.position._y; setIfrWinSize(winWidth, winHeight); } if (previewwin.classList.contains("__onsize")) { // 调整中显示当前大小(该状态需加入已开始判断) // console.log("dragging", rsdrag.position.x, rsdrag.position.y); resizehand.innerHTML = ` W: ${winWidth} px <br />H: ${winHeight} px `; } }); rsdrag.hook('__drag_begin', () => { // 绑定调整大小开始、结束状态样式、显示 previewwin.classList.add("__onsize"); }); rsdrag.hook('__drag_end', () => { previewwin.classList.remove("__onsize"); resizehand.innerHTML = ""; }); } function previewlink(evt) { // 在预览窗中加载链接 if (!!linkprev) { // 若有链接在预览中,去除其预览中状态 linkprev.classList.remove("__link__preved"); } linkprev = evt.target.parentNode; // 当前链接为预览中状态 linkprev.classList.add("__link__preved"); pre_ir.src = linkprev.href; // 加载页面,调整缩放 pre_ir.style.transform = "scale(" + scale + ")"; previewwin.classList.remove("__close"); // 预览窗去除关闭、添加加载中状态 previewwin.classList.add("__loading"); titlebox.innerHTML = linkprev.textContent; // 以链接文本为标题 setTimeout(() => { // 延时0.1秒(等待预览窗到位)显示、移动、大小 previewwin.classList.add("__link__visible"); let l = Math.max(minHgap, Math.min(window.innerWidth - winWidth - minHgap, evt.x)); let t = Math.max(minVgap, Math.min(window.innerHeight - winHeight - minVgap, evt.y)); setWinPosit(l, t); setPrevWinSize(winWidth, winHeight); closebtn.classList.remove("__close"); closebtn.classList.add("__loading"); }, 100); pre_ir.onload = () => { // iframe加载完成后去除加载中状态 closebtn.classList.remove("__loading"); previewwin.classList.remove("__loading"); }; } function setWinPosit(l, t) { // 根据屏幕位置设置网页位置 previewwin.style.left = l + window.scrollX + 'px'; previewwin.style.top = t + window.scrollY + 'px'; } function setPrevWinSize(w, h) { // 设置预览窗口大小 previewwin.style.width = w + 'px'; previewwin.style.height = h + 'px'; setIfrWinSize(w, h); } function setIfrWinSize(w, h) { // 根据放大率设置iframe窗口大小 var f = (1 - scale) / 2 * -1 / scale; pre_ir.width = w / scale; pre_ir.height = h / scale; pre_ir.style.marginLeft = (w * f) + 'px'; pre_ir.style.marginTop = (h * f) + 'px'; } function hidepreview(evt) { setPrevWinSize(100, 100); // 预览窗缩小效果 pre_ir.src = ''; setWinPosit(evt.x, evt.y); // 在鼠标位置消失 previewwin.classList.remove('__link__visible'); linkprev.classList.remove('__link__preved'); // 去除链接高亮中状态 closebtn.classList.add("__close"); setTimeout(() => { // 动画效果完成后添加关闭状态 previewwin.classList.add("__close"); }, animationtime * 1000 + 10); } function isPrevVisual() { // 预览窗是否可见 return previewwin && previewwin.classList.contains('__link__visible'); } function getLinksInThreeLayer(elem) { // 对当前元素及其下两层的链接进行提取 var links = []; elem.childNodes.forEach(cnode => { if (ispagelink(cnode)) { links.push(cnode); } else { cnode.childNodes.forEach(ccnode => { if (ispagelink(ccnode)) { links.push(ccnode); } else { ccnode.childNodes.forEach(cccnode => { if (ispagelink(cccnode)) { links.push(cccnode); } }); } }); } }); return links; } function ispagelink(node) { // 若节点是A且指向实网址(非js非锚点)返回true if (node.tagName !== "A" || !node.href) { return false; } const h = node.href, l = location.href; if (h.indexOf('javascript:') == 0 || h.replace(l.split('#')[0], "").indexOf("#") == 0) { return false; } else { return true; } } function creaElemIn(tagname, destin) { //在 destin 内末尾创建元素 tagname let theElem = destin.appendChild(document.createElement(tagname)); return theElem; } function addCSS(css, cssid) { // 创建带id的 style 节点 let stylenode = creaElemIn('style', document.getElementsByTagName('head')[0]); stylenode.textContent = css; stylenode.type = 'text/css'; stylenode.id = cssid || ''; } // 输入元素,返回对象{元素可见的宽、高、顶、左、一层父元素右侧余量} function getTrueSize(elem, posiz) { if (!posiz) { var p = elem.getBoundingClientRect(); posiz = { w: p.width, h: p.height, t: p.top, l: p.left, r: 0 }; } var pp = elem.parentNode.getBoundingClientRect(); if (posiz.r == 0) posiz.r = (pp.left + pp.width) - (posiz.l + posiz.w); // 父元素对当前元素的右侧余量 if (pp.width >= posiz.w && pp.height >= posiz.h && pp.top <= posiz.t && pp.left <= posiz.l) { return posiz; } else { return getTrueSize(elem.parentNode, { w: Math.min(posiz.w, pp.width), h: Math.min(posiz.h, pp.height), t: Math.max(posiz.t, pp.top), l: Math.max(posiz.l, pp.left), r: posiz.r }); } } // 对target拖动handle时,实现拖动的功能 // 输入:目标元素target,拖动位置参考系opt,拖动手柄handle // 输入opt:形如【{x:'right',y:'bottom'}】,或者width、height(右下角拖动) function endrag(target, opt, handle) { var p_x, p_y, isDragging; endrag = function (target, opt, handle) { return new endrag.proto(target, opt || {}, handle); } endrag.proto = function (target, opt, handle) { var self = this; this.target = target; this.style = target.style; this.handle = handle; var _x = opt.x !== 'right'; var _y = opt.y !== 'bottom'; this.x = opt.x; //_x ? 'left' : 'right'; this.y = opt.y; //_y ? 'top' : 'bottom'; // p_x = this.x; // p_y = this.y; this.xd = _x ? -1 : 1; this.yd = _y ? -1 : 1; this.computed_style = document.defaultView.getComputedStyle(target, ''); this.drag_begin = function (e) { self.__drag_begin(e); }; this.handle.addEventListener('mousedown', this.drag_begin, false); //only drag on handler this.dragging = function (e) { self.__dragging(e); }; document.addEventListener('mousemove', this.dragging, false); this.drag_end = function (e) { self.__drag_end(e); }; document.addEventListener('mouseup', this.drag_end, false); }; endrag.proto.prototype = { __drag_begin: function (e) { if (e.button == 0) { var _c = this.computed_style; this.isDragging = isDragging = true; this.position = { _x: parseFloat(_c[this.x]), _y: parseFloat(_c[this.y]), x: e.pageX, y: e.pageY }; e.preventDefault(); } }, __dragging: function (e) { if (!this.isDragging) return; var x = Math.floor(e.pageX), y = Math.floor(e.pageY), p = this.position; // prevent moving out of window var x_border = window.innerWidth - 40, y_border = window.innerHeight - 20; if (x - window.scrollX > x_border) x = window.scrollX + x_border; if (y - window.scrollY > y_border) y = window.scrollY + y_border; p._x = p._x + (p.x - x) * this.xd; p._y = p._y + (p.y - y) * this.yd; this.style[this.x] = p._x + 'px'; this.style[this.y] = p._y + 'px'; p.x = x; p.y = y; }, __drag_end: function (e) { if (e.button == 0) { if (this.isDragging) { this.isDragging = isDragging = false; } } }, hook: function (method, func) { if (typeof this[method] === 'function') { var o = this[method]; this[method] = function () { if (func.apply(this, arguments) === false) { return; } o.apply(this, arguments); }; } } }; return endrag(target, opt, handle); } function mixStringLength(str, size) { // 输出按size(字号px)计算的字符长度 var cvalue = str.replace(/\r\n/g, "\n").trim(); var cncnt = (cvalue.match(/[\u4e00-\u9fa5]/g) || []).length; //统一中文字范围 var kncnt = (cvalue.match(/[\u3040-\u30ff]/g) || []).length; //日文假名范围 var krcnt = (cvalue.match(/[\uac00-\ud7af]/g) || []).length; //韩文字范围 var ttcnt = cvalue.length; return ttcnt * size - (ttcnt - cncnt - kncnt - krcnt) * size / 2; } })();