Greasy Fork is available in English.
使用修饰键拖拽链接时在弹出窗口中打开链接,并在打开前提供预览,使用 Edge 的预读技术。同时在小窗口打开时在背后添加亚克力效果。
当前为
// ==UserScript==
// @name 小窗预览 轻量版
// @version 2.7
// @description 使用修饰键拖拽链接时在弹出窗口中打开链接,并在打开前提供预览,使用 Edge 的预读技术。同时在小窗口打开时在背后添加亚克力效果。
// @author hiisme
// @match *://*/*
// @grant GM_registerMenuCommand
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_info
// @namespace http://greasyfork.icu/users/217852
// ==/UserScript==
(function () {
'use strict';
const state = {
isDragging: false,
linkToPreload: null,
popupWindow: null,
acrylicOverlay: null,
};
const config = {
windowWidth: GM_getValue('windowWidth', 870),
windowHeight: GM_getValue('windowHeight', 530),
screenLeft: (window.screen.width - GM_getValue('windowWidth', 870)) / 2,
screenTop: (window.screen.height - GM_getValue('windowHeight', 530)) / 3,
blurIntensity: GM_getValue('blurIntensity', 20), // Changed to match script 2
blurEnabled: GM_getValue('blurEnabled', true),
closeOnMouseClick: GM_getValue('closeOnMouseClick', true),
closeOnScroll: GM_getValue('closeOnScroll', true),
};
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function preloadLink(link, attributes = {}) {
const preloadElement = document.createElement('link');
preloadElement.rel = 'preload';
preloadElement.href = link;
preloadElement.as = '*/*';
Object.assign(preloadElement, attributes);
document.head.appendChild(preloadElement);
await delay(1);
}
function createAcrylicOverlay() {
const acrylicOverlay = document.createElement('div');
acrylicOverlay.style.position = 'fixed';
acrylicOverlay.style.top = '0';
acrylicOverlay.style.left = '0';
acrylicOverlay.style.width = '100%';
acrylicOverlay.style.height = '100%';
acrylicOverlay.style.zIndex = '9999';
// Apply the blur effect from script 2
acrylicOverlay.style.backdropFilter = config.blurEnabled ? 'blur(20px)' : 'none';
if (config.closeOnMouseClick) {
acrylicOverlay.addEventListener('click', handleAcrylicOverlayClick);
}
document.body.appendChild(acrylicOverlay);
return acrylicOverlay;
}
function handleAcrylicOverlayClick(event) {
if (event.target === state.acrylicOverlay) {
closePopupWindow();
}
}
function removeAcrylicOverlay() {
if (state.acrylicOverlay) {
document.body.removeChild(state.acrylicOverlay);
state.acrylicOverlay = null;
}
}
function openPopupWindow(link) {
if (!state.popupWindow || state.popupWindow.closed) {
state.acrylicOverlay = createAcrylicOverlay();
state.popupWindow = window.open(link, '_blank', `width=${config.windowWidth},height=${config.windowHeight},left=${config.screenLeft},top=${config.screenTop}`);
// 启动定时检查弹出窗口状态
state.popupWindowChecker = setInterval(checkPopupWindowStatus, 200);
}
}
function closePopupWindow() {
if (state.popupWindow && !state.popupWindow.closed) {
state.popupWindow.close();
state.popupWindow = null;
removeAcrylicOverlay(); // 移除模糊效果
if (state.linkToPreload) {
removePreloadedLink(state.linkToPreload);
}
window.removeEventListener('scroll', closePopupOnScroll);
}
}
function checkPopupWindowStatus() {
if (state.popupWindow) {
if (state.popupWindow.closed) {
removeAcrylicOverlay(); // 弹出窗口关闭时移除模糊效果
clearInterval(state.popupWindowChecker);
} else {
const width = state.popupWindow.innerWidth;
const height = state.popupWindow.innerHeight;
const left = state.popupWindow.screenX;
const top = state.popupWindow.screenY;
// 可以根据需要处理窗口尺寸和位置变化
}
}
}
function removePreloadedLink(link) {
const preloadElement = document.querySelector(`link[href="${link}"]`);
if (preloadElement) {
document.head.removeChild(preloadElement);
}
}
function closePopupOnScroll() {
if (state.popupWindow && !state.popupWindow.closed) {
closePopupWindow();
}
}
function registerMenuCommand(label, action) {
return GM_registerMenuCommand(label, () => {
action();
updateMenuCommands();
});
}
const menuCommands = [
{ label: `切换模糊效果 (${config.blurEnabled ? '开' : '关'})`, action: toggleBlurEffect },
{ label: `设置模糊强度 (${config.blurIntensity})`, action: setBlurIntensity },
{ label: `切换点击关闭小窗 (${config.closeOnMouseClick ? '开' : '关'})`, action: toggleCloseOnMouseClick },
{ label: `切换滚动关闭小窗 (${config.closeOnScroll ? '开' : '关'})`, action: toggleCloseOnScroll },
{ label: `设置小窗宽度 (${config.windowWidth})`, action: () => { setWindowSize('width'); } },
{ label: `设置小窗高度 (${config.windowHeight})`, action: () => { setWindowSize('height'); } }
];
function toggleBlurEffect() {
config.blurEnabled = !config.blurEnabled;
GM_setValue('blurEnabled', config.blurEnabled);
}
function setBlurIntensity() {
const intensity = prompt('输入模糊强度(0-10):', config.blurIntensity);
if (intensity !== null) {
config.blurIntensity = parseInt(intensity, 10);
GM_setValue('blurIntensity', config.blurIntensity);
}
}
function toggleCloseOnMouseClick() {
config.closeOnMouseClick = !config.closeOnMouseClick;
GM_setValue('closeOnMouseClick', config.closeOnMouseClick);
}
function toggleCloseOnScroll() {
config.closeOnScroll = !config.closeOnScroll;
handleScrollCommand();
GM_setValue('closeOnScroll', config.closeOnScroll);
}
function handleScrollCommand() {
if (config.closeOnScroll) {
window.addEventListener('scroll', closePopupOnScroll, { once: true });
} else {
window.removeEventListener('scroll', closePopupOnScroll);
}
}
function setWindowSize(dimension) {
const size = prompt(`输入小窗口${dimension}(像素):`, config[dimension === 'width' ? 'windowWidth' : 'windowHeight']);
if (size !== null) {
config[dimension === 'width' ? 'windowWidth' : 'windowHeight'] = parseInt(size, 10);
GM_setValue(dimension === 'width' ? 'windowWidth' : 'windowHeight', config[dimension === 'width' ? 'windowWidth' : 'windowHeight']);
if (state.popupWindow && !state.popupWindow.closed) {
state.popupWindow.resizeTo(config.windowWidth, config.windowHeight);
}
}
}
function updateMenuCommands() {
menuCommands.forEach((command) => {
const menuCommand = registerMenuCommand(command.label, command.action);
GM_info[`menuCommand${toTitleCase(command.label)}`] = menuCommand;
});
}
function toTitleCase(str) {
return str.replace(/\w\S*/g, (txt) => { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); });
}
updateMenuCommands();
document.body.addEventListener('dragstart', async (event) => {
const linkElement = event.target.tagName === 'A' ? event.target : event.target.closest('a');
if (linkElement) {
const link = linkElement.href;
state.isDragging = true;
state.linkToPreload = link;
await preloadLink(state.linkToPreload, { importance: 'high' });
if (config.closeOnScroll) {
window.addEventListener('scroll', closePopupOnScroll, { once: true });
}
}
});
document.body.addEventListener('dragend', () => {
if (state.isDragging && state.linkToPreload) {
state.isDragging = false;
openPopupWindow(state.linkToPreload);
state.linkToPreload = null;
}
});
document.body.addEventListener('wheel', () => {
if (config.closeOnScroll) {
closePopupWindow();
}
});
document.body.addEventListener('click', (event) => {
if (event.target === state.acrylicOverlay) {
removeAcrylicOverlay();
}
});
})();