--- title: 自定义右键菜单 categories: 建站手札 tags: 网站 series: webcustom abbrlink: 8bdb35fb cover: https://pic.biss.click/image/9c4021c3-3111-4e19-acca-52ec899aa0b4.webp summary: >- 这篇文章介绍了如何在自定义右键菜单中添加各种功能,包括返回、前进、刷新、滚动到页面不同位置、复制文本、搜索页面、打开链接、粘贴内容、复制本文地址、在新窗口打开链接、保存图片、随机文章浏览、切换深色模式、繁简转换、阅读模式以及隐私声明、Cookie协议和版权声明等。同时,文章还提供了创建Pug文件和JavaScript文件的步骤,详细说明了如何编写右键菜单的HTML结构和交互逻辑。 date: 2025-08-11 16:02:12 --- # 演示 本站右键即可查看,和原有菜单相比比较美观 # 新建pug文件 在 `\themes\butterfly\layout\includes`新建 `rightmenu.pug` ```pug #rightMenu.js-pjax .rightMenu-group.rightMenu-small a.rightMenu-item(href="javascript:window.history.back();") i.fa.fa-arrow-left a.rightMenu-item(href="javascript:window.history.forward();") i.fa.fa-arrow-right a.rightMenu-item(href="javascript:window.location.reload();") i.fa.fa-refresh a.rightMenu-item(href="javascript:window.scrollTo(0, 0);") i.fa.fa-arrow-up .rightMenu-group.rightMenu-line.hide#menu-text a.rightMenu-item(href="javascript:rmf.copySelect();") i.fa.fa-copy span='复制' a.rightMenu-item(href="javascript:rmf.searchinThisPage();") i.fas.fa-search span='站内搜索' .rightMenu-group.rightMenu-line.hide#menu-too a.rightMenu-item(href="javascript:window.open(window.getSelection().toString());window.location.reload();") i.fa.fa-link span='转到链接' .rightMenu-group.rightMenu-line.hide#menu-paste a.rightMenu-item(href='javascript:rmf.paste()') i.fa.fa-copy span='粘贴' .rightMenu-group.rightMenu-line.hide#menu-post a.rightMenu-item(href="javascript:rmf.copyWordsLink()") i.fa.fa-link span='复制本文地址' .rightMenu-group.rightMenu-line.hide#menu-to a.rightMenu-item(href="javascript:rmf.openWithNewTab()") i.fa.fa-window-restore span='新窗口打开' a.rightMenu-item(href="javascript:rmf.open()") i.fa.fa-link span='转到链接' a.rightMenu-item(href="javascript:rmf.copyLink()") i.fa.fa-copy span='复制链接' .rightMenu-group.rightMenu-line.hide#menu-img a.rightMenu-item(href="javascript:rmf.saveAs()") i.fa.fa-download span='保存图片' a.rightMenu-item(href="javascript:rmf.openWithNewTab()") i.fa.fa-window-restore span='在新窗口打开' a.rightMenu-item(href="javascript:rmf.click()") i.fa.fa-arrows-alt span='全屏显示' a.rightMenu-item(href="javascript:rmf.copyLink()") i.fa.fa-copy span='复制图片链接' .rightMenu-group.rightMenu-line a.rightMenu-item(href="javascript:randomPost()") i.fa.fa-paper-plane span='随便逛逛' a.rightMenu-item(href="javascript:rmf.switchDarkMode();") i.fa.fa-moon span='昼夜切换' a.rightMenu-item(href="javascript:rmf.translate();") i.iconfont.icon-fanti span='繁简转换' if is_post()||is_page() a.rightMenu-item(href="javascript:rmf.switchReadMode();") i.fa.fa-book span='阅读模式' a.rightMenu-item(href="javascript:pjax.loadUrl(\"/privacy/\");") i.fa.fa-info-circle span='隐私声明' a.rightMenu-item(href="javascript:pjax.loadUrl(\"/cookie/\");") i.fa.fa-info-circle span='Cookie协议' a.rightMenu-item(href="javascript:pjax.loadUrl(\"/cc/\");") i.fa.fa-info-circle span='版权声明' ``` # 新建js文件 创建 `\themes\butterfly\source\js\rightmenu.js` ```js function setMask() {//设置遮罩层 if (document.getElementsByClassName("rmMask")[0] !== undefined) { return document.getElementsByClassName("rmMask")[0]; } mask = document.createElement('div'); mask.className = "rmMask"; mask.style.width = window.innerWidth + 'px'; mask.style.height = window.innerHeight + 'px'; mask.style.background = '#fff'; mask.style.opacity = '.0'; mask.style.position = 'fixed'; mask.style.top = '0'; mask.style.left = '0'; mask.style.zIndex = 998; document.body.appendChild(mask); document.getElementById("rightMenu").style.zIndex = 19198; return mask; } function insertAtCursor(myField, myValue) { //IE 浏览器 if (document.selection) { myField.focus(); sel = document.selection.createRange(); sel.text = myValue; sel.select(); } //FireFox、Chrome等 else if (myField.selectionStart || myField.selectionStart === '0') { var startPos = myField.selectionStart; var endPos = myField.selectionEnd; // 保存滚动条 var restoreTop = myField.scrollTop; myField.value = myField.value.substring(0, startPos) + myValue + myField.value.substring(endPos, myField.value.length); if (restoreTop > 0) { myField.scrollTop = restoreTop; } myField.focus(); myField.selectionStart = startPos + myValue.length; myField.selectionEnd = startPos + myValue.length; } else { myField.value += myValue; myField.focus(); } } let rmf = {}; rmf.showRightMenu = function (isTrue, x = 0, y = 0) { let $rightMenu = $('#rightMenu'); $rightMenu.css('top', x + 'px').css('left', y + 'px'); if (isTrue) { $rightMenu.show(); } else { $rightMenu.hide(); } } rmf.switchDarkMode = function () { const nowMode = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light' if (nowMode === 'light') { activateDarkMode() saveToLocal.set('theme', 'dark', 2) GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.day_to_night) } else { activateLightMode() saveToLocal.set('theme', 'light', 2) GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.night_to_day) } // handle some cases typeof utterancesTheme === 'function' && utterancesTheme() typeof FB === 'object' && window.loadFBComment() window.DISQUS && document.getElementById('disqus_thread').children.length && setTimeout(() => window.disqusReset(), 200) switchPostChart(); }; rmf.copyWordsLink = function () { const decodedUrl = decodeURIComponent(window.location.href); // 解码 URL navigator.clipboard.writeText(decodedUrl) .then(() => { Snackbar.show({ text: '链接复制成功!快去分享吧!', pos: 'top-right', showAction: false }); }) }; rmf.switchReadMode = function () { const $body = document.body $body.classList.add('read-mode') const newEle = document.createElement('button') newEle.type = 'button' newEle.className = 'fas fa-sign-out-alt exit-readmode' $body.appendChild(newEle) function clickFn() { $body.classList.remove('read-mode') newEle.remove() newEle.removeEventListener('click', clickFn) } newEle.addEventListener('click', clickFn) } //复制选中文字 rmf.copySelect = function () { navigator.clipboard.writeText(document.getSelection().toString()).then(() => { Snackbar.show({ text: '已复制选中文字!', pos: 'top-right', showAction: false, }); }); } //回到顶部 rmf.scrollToTop = function () { document.getElementsByClassName("menus_items")[1].setAttribute("style", ""); document.getElementById("name-container").setAttribute("style", "display:none"); btf.scrollToDest(0, 500); } rmf.translate = function () { document.getElementById("translateLink").click(); } rmf.searchinThisPage = () => { let mask = setMask(); // 确保 mask 元素存在于 document.body 中 document.getElementsByClassName("local-search-box--input")[0].value = window.getSelection().toString(); document.getElementsByClassName("search")[0].click(); var evt = document.createEvent("HTMLEvents"); evt.initEvent("input", false, false); document.getElementsByClassName("local-search-box--input")[0].dispatchEvent(evt); // 在尝试移除 mask 元素之前检查它是否存在于 document.body 中 if (document.body.contains(mask)) { document.body.removeChild(mask); } } document.body.addEventListener('touchmove', function (e) { }, {passive: false}); function popupMenu() { //window.oncontextmenu=function(){return false;} window.oncontextmenu = function (event) { Snackbar.show({ text: '按住 Ctrl 再点击右键,即可恢复原界面哦', pos: 'bottom-left', showAction: false }); if (event.ctrlKey || document.body.clientWidth < 900) return true; $('.rightMenu-group.hide').hide(); if (document.getSelection().toString()) { $('#menu-text').show(); } if (document.getElementById('post')) { $('#menu-post').show(); } else { if (document.getElementById('page')) { $('#menu-post').show(); } } var el = window.document.body; el = event.target; var a = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w.-]+)+[\w\-._~:\/?#[\]@!$&'*+,;=]+$/ if (a.test(window.getSelection().toString()) && el.tagName !== "A") { $('#menu-too').show() } if (el.tagName === 'A') { $('#menu-to').show() rmf.open = function () { if (el.href.indexOf("http://") === -1 && el.href.indexOf("https://") === -1 || el.href.indexOf("blog.june-pj.cn") !== -1) { pjax.loadUrl(el.href) } else { location.href = el.href } } rmf.openWithNewTab = function () { window.open(el.href); // window.location.reload(); } rmf.copyLink = function () { const url = el.href; navigator.clipboard.writeText(url); Snackbar.show({ text: '链接复制成功!快去分享吧!', pos: 'top-right', showAction: false }); }; } if (el.tagName === 'IMG') { $('#menu-img').show() rmf.openWithNewTab = function () { window.open(el.src); // window.location.reload(); } rmf.click = function () { el.click() } rmf.copyLink = function () { const url = el.src navigator.clipboard.writeText(url); Snackbar.show({ text: '链接复制成功!快去分享吧!', pos: 'top-right', showAction: false }); } rmf.saveAs = function () { var a = document.createElement('a'); a.href = el.src; // 获取图片的文件名部分 a.download = el.src.split('/').pop(); // 使用图片的文件名作为下载文件名 a.style.display = 'none'; // 隐藏下载链接 document.body.appendChild(a); a.click(); document.body.removeChild(a); } } else if (el.tagName === "TEXTAREA" || el.tagName === "INPUT") { $('#menu-paste').show(); // rmf.paste=function(){ // input.addEventListener('paste', async event => { // event.preventDefault(); // const text = await navigator.clipboard.readText(); // el.value+=text; // }); // } rmf.paste = function () { navigator.permissions .query({ name: 'clipboard-read' }) .then(result => { if (result.state === 'granted' || result.state === 'prompt') { //读取剪贴板 navigator.clipboard.readText().then(text => { console.log(text) insertAtCursor(el, text) }) } else { Snackbar.show({ text: '请允许读取剪贴板!', pos: 'top-center', showAction: false, }) } }) } } let pageX = event.clientX + 10; let pageY = event.clientY; let rmWidth = $('#rightMenu').width(); let rmHeight = $('#rightMenu').height(); if (pageX + rmWidth > window.innerWidth) { pageX -= rmWidth + 10; } if (pageY + rmHeight > window.innerHeight) { pageY -= pageY + rmHeight - window.innerHeight; } mask = setMask(); window.onscroll = () => { rmf.showRightMenu(false); window.onscroll = () => { } if (document.body.contains(mask)) { document.body.removeChild(mask); } } $(".rightMenu-item").click(() => { if (document.body.contains(mask)) { document.body.removeChild(mask); } }); $(window).resize(() => { rmf.showRightMenu(false); if (document.body.contains(mask)) { document.body.removeChild(mask); } }); mask.onclick = () => { if (document.body.contains(mask)) { document.body.removeChild(mask); } }; rmf.showRightMenu(true, pageY, pageX); return false; }; window.addEventListener('click', function () { rmf.showRightMenu(false); }); } if (!(navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) { popupMenu() } const box = document.documentElement function addLongtabListener(target, callback) { let timer = 0 // 初始化timer target.ontouchstart = () => { timer = 0 // 重置timer timer = setTimeout(() => { callback(); timer = 0 }, 380) // 超时器能成功执行,说明是长按 } target.ontouchmove = () => { clearTimeout(timer) // 如果来到这里,说明是滑动 timer = 0 } target.ontouchend = () => { // 到这里如果timer有值,说明此触摸时间不足380ms,是点击 if (timer) { clearTimeout(timer) } } } addLongtabListener(box, popupMenu) ``` # 创建css 创建 `\themes\butterfly\source\css\rightmenu.css` ```css /* rightMenu */ [data-theme='light'] #rightMenu{ display: none; position: fixed; width: 160px; height: fit-content; top: 10%; left: 10%; background-color: var(--card-bg); border: 1px solid rgb(210,210,210);; border-radius: 8px; z-index: 100; box-shadow: 3px 3px 5px #88888894; background-color: var(--june-white-acrylic1); backdrop-filter: blur(30px); } [data-theme='dark'] #rightMenu{ display: none; position: fixed; width: 160px; height: fit-content; top: 10%; left: 10%; background-color: var(--card-bg); border: 1px solid rgb(210,210,210);; border-radius: 8px; z-index: 100; box-shadow: 3px 3px 5px #88888894; background-color: var(--june-black-acrylic1); backdrop-filter: blur(30px); } #rightMenu .rightMenu-group{ padding: 7px 6px; } #rightMenu .rightMenu-group:not(:nth-last-child(1)){ border-bottom: 1px solid rgb(180,180,180); } #rightMenu .rightMenu-group.rightMenu-small{ display: flex; justify-content: space-between; } #rightMenu .rightMenu-group .rightMenu-item{ height: 30px; line-height: 30px; border-radius: 8px; transition: 0.3s; color: var(--font-color); } #rightMenu .rightMenu-group.rightMenu-line .rightMenu-item{ display: flex; height: 40px; line-height: 40px; padding: 0 4px; } #rightMenu .rightMenu-group .rightMenu-item:hover{ background-color: var(--text-bg-hover); box-shadow: 0px 0px 5px var(--june-border); } #rightMenu .rightMenu-group .rightMenu-item i{ display: inline-block; text-align: center; line-height: 30px; width: 30px; height: 30px; padding: 0 5px; } #rightMenu .rightMenu-group .rightMenu-item span{ line-height: 30px; } #rightMenu:hover{ border: 1px solid var(--june-theme); } #rightMenu .rightMenu-group.rightMenu-line .rightMenu-item *{ height: 40px; line-height: 40px; } .rightMenu-group.hide{ display: none; } .rightMenu-item:hover{ color:white!important; background-color:var(--june-theme)!important; } ``` # 引入 ```yml - - ```