优美地展示网页二维码,供手机扫描,并支持一键复制链接,UI 风格仿苹果。
// ==UserScript==
// @name 网页转二维码
// @namespace http://tampermonkey.net/
// @match *://*/*
// @grant GM_registerMenuCommand
// @grant GM_addStyle
// @grant GM_setClipboard
// @version 2.0
// @license MIT
// @author BergerLee
// @description 优美地展示网页二维码,供手机扫描,并支持一键复制链接,UI 风格仿苹果。
// ==/UserScript==
(function () {
'use strict';
GM_addStyle(`
/* 弹窗容器:浮动在页面中央,使用柔和阴影和圆角 */
.apple-qr-dialog {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0.95);
width: 340px; /* 适当的宽度 */
padding: 24px;
background: rgba(45, 45, 45, 0.85); /* 半透明深色背景 */
backdrop-filter: blur(20px); /* 核心:毛玻璃效果 */
border-radius: 20px; /* 大圆角 */
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2), 0 0 10px rgba(0, 0, 0, 0.15);
z-index: 99999;
opacity: 0; /* 初始隐藏 */
visibility: hidden;
transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s ease;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
color: #f0f0f0; /* 浅色文字 */
text-align: center;
}
/* 弹窗显示时的状态 */
.apple-qr-dialog.visible {
opacity: 1;
visibility: visible;
transform: translate(-50%, -50%) scale(1);
}
/* 弹窗标题 */
.apple-qr-dialog h3 {
margin: 0 0 12px 0;
font-size: 18px;
font-weight: 600;
letter-spacing: -0.5px;
color: #ffffff;
}
/* 二维码容器 */
.apple-qr-container {
width: 200px;
height: 200px;
margin: 0 auto 16px;
padding: 8px; /* 留白 */
background: #ffffff;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.apple-qr-container canvas {
display: block;
width: 100%;
height: 100%;
border-radius: 8px; /* 二维码内部圆角 */
}
/* URL显示与复制部分 */
.apple-qr-url-box {
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.1);
border-radius: 10px;
padding: 8px 12px;
margin-bottom: 16px;
overflow: hidden;
white-space: nowrap;
}
.apple-qr-url {
flex-grow: 1;
font-size: 13px;
color: #d0d0d0;
overflow: hidden;
text-overflow: ellipsis; /* 超出部分显示省略号 */
cursor: pointer;
}
.apple-qr-copy-btn {
background: none;
border: none;
color: #b0b0b0;
cursor: pointer;
font-size: 14px;
padding: 0;
transition: color 0.2s ease;
}
.apple-qr-copy-btn:hover {
color: #ffffff;
}
/* 关闭按钮 */
.apple-qr-close-btn {
position: absolute;
top: 12px;
right: 12px;
width: 28px;
height: 28px;
background: rgba(255, 255, 255, 0.1);
border: none;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
color: #f0f0f0;
font-size: 16px;
line-height: 1;
transition: background-color 0.2s ease;
}
.apple-qr-close-btn:hover {
background: rgba(255, 255, 255, 0.2);
}
/* 底部信息 */
.apple-qr-footer {
font-size: 11px;
color: #a0a0a0;
margin-top: 10px;
}
.apple-qr-footer a {
color: #b0b0b0;
text-decoration: none;
font-weight: 500;
transition: color 0.2s ease;
}
.apple-qr-footer a:hover {
color: #ffffff;
}
`);
const qriousScript = document.createElement('script');
qriousScript.src = 'https://cdnjs.cloudflare.com/ajax/libs/qrious/4.0.2/qrious.min.js';
qriousScript.onload = () => {
init();
};
document.head.appendChild(qriousScript);
function init() {
// 注册 Tampermonkey 菜单命令,显示当前系统的快捷键
GM_registerMenuCommand(`✨ 生成二维码 (Ctrl + M)`, () => showQRDialog(location.href));
// 注册快捷键监听器
window.addEventListener('keydown', (event) => {
// 根据操作系统判断正确的修饰键和字符键
const modifierKey = event.ctrlKey;
const targetKey = 'm'; // 统一使用小写,keydown事件不区分大小写
if (modifierKey && event.key === targetKey) {
event.preventDefault();
showQRDialog(location.href);
}
});
}
/**
* 显示 Apple 风格的二维码弹窗
* @param {string} url - 需要生成二维码的 URL
*/
function showQRDialog(url) {
// 如果弹窗已存在,则直接返回
if (document.getElementById('apple-qr-dialog')) {
return;
}
// 创建弹窗容器
const dialog = document.createElement('div');
dialog.id = 'apple-qr-dialog';
dialog.className = 'apple-qr-dialog';
// 弹窗内容 HTML
dialog.innerHTML = `
<button class="apple-qr-close-btn">×</button>
<h3>本页面二维码</h3>
<div class="apple-qr-container">
<canvas></canvas>
</div>
<div class="apple-qr-url-box">
<div class="apple-qr-url" title="${url}">${url}</div>
<button class="apple-qr-copy-btn">📋</button>
</div>
<p class="apple-qr-footer">由 <a href="https://greasyfork.org/zh-CN/users/747774-berger-lee-berger" target="_blank">BergerLee</a> 制作</p>
`;
document.body.appendChild(dialog);
// 渲染二维码
const canvas = dialog.querySelector('canvas');
new QRious({
element: canvas,
value: url,
size: 200,
background: 'transparent',
foreground: '#000000'
});
// 添加事件监听
setupDialogEvents(dialog, url);
// 延迟添加 visible class,触发 CSS 动画
setTimeout(() => {
dialog.classList.add('visible');
}, 10);
}
/**
* 为弹窗设置事件监听器
* @param {HTMLElement} dialog - 弹窗 DOM 元素
* @param {string} url - 待复制的 URL
*/
function setupDialogEvents(dialog, url) {
const closeBtn = dialog.querySelector('.apple-qr-close-btn');
const urlBox = dialog.querySelector('.apple-qr-url-box');
const copyBtn = dialog.querySelector('.apple-qr-copy-btn');
const originalCopyBtnText = copyBtn.innerText;
// 关闭弹窗
const closeDialog = () => {
dialog.classList.remove('visible');
setTimeout(() => {
if (dialog.parentNode) {
dialog.parentNode.removeChild(dialog);
}
}, 300); // 等待动画完成再移除元素
};
// 关闭按钮
closeBtn.addEventListener('click', closeDialog);
// 点击 URL 框也进行复制
urlBox.addEventListener('click', async () => {
try {
GM_setClipboard(url);
// 提供复制成功的视觉反馈
copyBtn.innerText = '✅';
setTimeout(() => {
copyBtn.innerText = originalCopyBtnText;
}, 2000);
} catch (err) {
console.error('复制失败:', err);
copyBtn.innerText = '❌';
setTimeout(() => {
copyBtn.innerText = originalCopyBtnText;
}, 2000);
}
});
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && document.body.contains(dialog)) {
closeDialog();
}
});
}
})();