Fluid -39- 自定义右键菜单

2024-01-25 08:22:11 浏览数 (3)

博客的右键菜单,本质上很简单,就是在当前 Html 界面劫持右键单击事件,禁止默认右键弹出,把自己的右键菜单在当前鼠标位置展示出来。

实现思路

  • 核心技术:自定义网页右键菜单
  • 实现流程:
    • 建立右键菜单:通过 hexo 注入定义,自定义 css 实现样式管理
    • 劫持右键单击事件: js 实现,关闭默认行为,展示自定义的菜单
    • 原始右键功能:为了方便有需要的朋友,将 Ctrl 右键 作为原始右键提供出来
    • 展示提示信息:记录当前右键单击次数,在一定次数时展示提示信息以方便需要使用原始右键菜单的访客

实现过程

建立右键菜单

为了不影响正常数据加载,我决定在 BodyEnd 注入该代码段

source/_inject 文件夹创建 bodyEnd.ejs 文件,在 scripts/page.js 中引入该注入文件:

代码语言:text复制
hexo.extend.filter.register('theme_inject', function(injects) {
  injects.bodyEnd.file('default', "source/_inject/bodyEnd.ejs");
});

bodyEnd.ejs 文件写入

代码语言:text复制
<div id="tooltip-rightmenu" class="tooltip-rightmenu">如需原始右键菜单请按下 <strong>Ctrl 右键</strong></div>

<div id="rightmenu-wrapper" style="">
  <ul class="list-v rightmenu" id="rightmenu-content">
	  <li class="navigation menuNavigation-Content">
		<a class="nav icon-only fix-cursor-default" onclick="history.back()"><i class="iconfont icon-zuojiantou1"></i></a>
		<a class="nav icon-only fix-cursor-default" onclick="history.forward()"><i class="iconfont icon-youjiantou1"></i></a>
		<a class="nav icon-only fix-cursor-default" onclick="window.location.reload()"><i class="iconfont icon-shuaxin"></i></a>
		<a  aria-label="TOP" href="#" role="button"><i class="iconfont icon-xiangshang"></i></a>
	  </li>

		<hr class="menuLoad-Content" style="display: block;">
	  <li class="menuLoad-Content" style="display: block;">
		<a class="vlts-menu fix-cursor-default" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
		  <span>
			  <i class="iconfont icon-sousuo1 rightmenu-icon"></i>
			  站内搜索
		  </span>
		</a>
	  </li>

	  <li class="menuLoad-Content" style="display: block;">
		<a class="vlts-menu fix-cursor-default"  href="https://www.zywvvd.com/messagebd/" data-group="link">
		  <span>
			  <i class="iconfont icon-yangshi_icon_tongyong_chat rightmenu-icon">  </i>
			   留言吐槽 
		   </span>
		</a>
	  </li>


	  <li class="menuLoad-Content" style="display: block;">
		<a class="vlts-menu fix-cursor-default" id="help" target="_blank" rel="noopener" href="https://www.foreverblog.cn/go.html" data-group="link">
		<span>
			  <i class="iconfont icon-a-BlackHole rightmenu-icon"></i>
			  虫洞穿梭
		  </span>
		</a>
	  </li>

	<a id="scroll-top-button" aria-label="TOP" href="#" role="button" style="bottom: 20px; right: 52.6364px;">
        <i class="iconfont icon-xiangshangjiantou" aria-hidden="true"></i>
      </a>

	<hr class="menuLoad-Content" style="display: block;">
	

  </ul>
</div>

<link href="/css/custom.css"type="text/css"rel="stylesheet"/>
<script src="/vvd_js/right_menu.js" type="text/javascript"></script>
<link href="/css/right_menu.css"type="text/css"rel="stylesheet"/>

代码作为示例,事实上需要按照自己需求调整,核心目的是建立右键菜单。

定义右键菜单样式

source/css/custom.css 中添加图标 (我是放在这里的)

代码语言:text复制
@font-face {
  font-family: "iconfont"; /* Project id 3859637 */
  src: url('//at.alicdn.com/t/c/font_3859637_jxuiuw0et3.woff2?t=1705932159225') format('woff2'),
       url('//at.alicdn.com/t/c/font_3859637_jxuiuw0et3.woff?t=1705932159225') format('woff'),
       url('//at.alicdn.com/t/c/font_3859637_jxuiuw0et3.ttf?t=1705932159225') format('truetype');
}

.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.icon-xiangshang:before {
  content: "e601";
}

.icon-zuojiantou:before {
  content: "e64e";
}

.icon-xiangshang2:before {
  content: "e76e";
}

.icon-xiangyoujiantou:before {
  content: "e65f";
}

.icon-youjiantou:before {
  content: "e62d";
}

.icon-sousuo1:before {
  content: "e665";
}

.icon-shuaxin:before {
  content: "e6b2";
}

.icon-youjiantou1:before {
  content: "e644";
}

.icon-youjiantou2:before {
  content: "e678";
}

.icon-shuaxin1:before {
  content: "ec08";
}

.icon-zuojiantou1:before {
  content: "e642";
}

.icon-sousuo2:before {
  content: "e612";
}

.icon-zuojiantou2:before {
  content: "e629";
}

.icon-xiangshang1:before {
  content: "e645";
}

.icon-sousuo3:before {
  content: "e6c7";
}

.icon-quanxianfuzhi:before {
  content: "e62b";
}

.icon-icon-1:before {
  content: "e62c";
}

.icon-xiangshangjiantou:before {
  content: "e61f";
}

.icon-liaotianjilu:before {
  content: "e663";
}

.icon-24gf-bubblesDots6:before {
  content: "e95d";
}

.icon-24gf-bubblesDots4:before {
  content: "e95e";
}

.icon-yangshi_icon_tongyong_chat:before {
  content: "e664";
}

.icon-41shuoshuo:before {
  content: "e658";
}

.icon-git:before {
  content: "e799";
}

.icon-duomeit:before {
  content: "e621";
}

.icon-meiti:before {
  content: "e636";
}

.icon-xuniyingpan:before {
  content: "ea6c";
}

.icon-guanyuwomen:before {
  content: "e61e";
}

.icon-dingyue:before {
  content: "e600";
}

.icon-pengyoufill:before {
  content: "e745";
}

.icon-diqiu:before {
  content: "e7b9";
}

.icon-wangzhan:before {
  content: "e628";
}

.icon-chuansong:before {
  content: "e602";
}

.icon-icon-:before {
  content: "e62a";
}

.icon-lianjie:before {
  content: "eadc";
}

.icon-sousuo:before {
  content: "eafe";
}

.icon-jiankong:before {
  content: "eb37";
}

.icon-geren:before {
  content: "e670";
}

.icon-shuji1:before {
  content: "e6b7";
}

.icon-momo:before {
  content: "e8d9";
}

.icon-tongji2:before {
  content: "e61a";
}

.icon-tongjifenxi-xiangmubiaogetongji:before {
  content: "e626";
}

.icon-train1:before {
  content: "e742";
}

.icon-ic_fly:before {
  content: "e6bb";
}

.icon-a-BlackHole:before {
  content: "e95a";
}

source/css/right_menu.css 中定义右键菜单样式:

重点参考 黑兔小九 大佬

代码语言:text复制
div#rightmenu-wrapper {
    display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
    display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
    display: none;
    position: fixed;
    z-index: 2147483648;
    user-select: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
}

ul.list-v.rightmenu {
    display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
    display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
    display: block;
	background-color: var(--board-bg-color);
    max-width: 240px;
    overflow: hidden;
}

ul.list-v {
    z-index: 1;
    display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
    display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
    display: none;
    position: absolute;
    background: var(--color-card);
    box-shadow: 0 2px 4px 0px rgba(0,0,0,0.08), 0 4px 8px 0px rgba(0,0,0,0.08), 0 8px 16px 0px rgba(0,0,0,0.08);
    -webkit-box-shadow: 0 2px 4px 0px rgba(0,0,0,0.08), 0 4px 8px 0px rgba(0,0,0,0.08), 0 8px 16px 0px rgba(0,0,0,0.08);
    margin-top: -6px;
    border-radius: 4px;
    -webkit-border-radius: 4px;
    padding: 8px 0;
}


ul.list-v.rightmenu li.navigation, ul.list-v.rightmenu li.music {
    display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
    display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
    display: -ms-flexbox /* TWEENER - IE 10 */;
    display: -webkit-flex /* NEW - Chrome */;
    display: flex /* NEW, Spec - Opera 12.1, Firefox 20  */;
    display: flex;
    justify-content: space-between;
    -webkit-justify-content: space-between;
    -khtml-justify-content: space-between;
    -moz-justify-content: space-between;
    -o-justify-content: space-between;
    -ms-justify-content: space-between;
}

ul.list-v >li {
    white-space: nowrap;
    word-break: keep-all;
}


ul.list-v hr {
    margin-top: 8px;
    margin-bottom: 8px;
}

ul.list-v.rightmenu li.navigation a.nav i, ul.list-v.rightmenu li.music a.nav i {
    margin: 0;
    width: 32px;
    line-height: 32px;
}


ul.list-v >li {
    white-space: nowrap;
    word-break: keep-all;
}

ul.list-v.rightmenu li.navigation a.nav:first-child, ul.list-v.rightmenu li.music a.nav:first-child {
    margin-left: 3px;
}

ul.list-v.rightmenu a.vlts-menu {
    text-overflow: ellipsis;
    overflow: hidden;
    line-height: 36px;
    font-weight: normal;
}

.rightmenu-icon{
	margin: 0 11px 0 8px;
}



ul.list-v >li>a {
    transition: all 0.28s ease;
    -webkit-transition: all 0.28s ease;
    -khtml-transition: all 0.28s ease;
    -moz-transition: all 0.28s ease;
    -o-transition: all 0.28s ease;
    -ms-transition: all 0.28s ease;
    display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
    display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
    display: block;
    color: var(--text-color);
    font-size: 1rem;
    font-weight: bold;
    line-height: 36px;
    padding: 0 8px 0 8px;
    text-overflow: ellipsis;
    margin: 0 4px;
    border-radius: 4px;
    -webkit-border-radius: 4px;
}

ul.list-v >li>a :hover{
    color: var(--link-hover-color)
}


ul.list-v.rightmenu a {
    cursor: default;
}


/* 信息提示框 */

.tooltip-rightmenu {
position: fixed;
top: 10%;
left: 50%;
transform: translate(-50%, -50%); /* 居中 */
background: var(--text-color);
color: #fff;
padding: 10px 25px;
border-radius: 5px;
opacity: 0;
z-index: 99;
transition: opacity 1s ease-in-out;
}

.show-tooltip {
opacity: 0.8;
}

js 事件劫持

source/vvd_js 中创建 right_menu.js

代码语言:text复制

var right_cilck_num = 0;
window.oncontextmenu = function(e){
	// 检查是否按下了Ctrl键
	if (e.ctrlKey) {
		return true;
	}

	e.preventDefault(); //阻止浏览器自带的右键菜单显示
	var menu = document.getElementById("rightmenu-wrapper");
	menu.style.display = "block"; //将自定义的“右键菜单”显示出来
	menu.style.left = e.clientX   "px";  //设置位置,跟随鼠标
	menu.style.top = e.clientY "px"; 
	right_cilck_num = right_cilck_num  1;
	
	if(right_cilck_num %7== 1){
	      const tooltip = document.getElementById('tooltip-rightmenu');
	      tooltip.classList.add('show-tooltip');

	      // 3秒后隐藏提示框
	      setTimeout(() => {
		tooltip.classList.remove('show-tooltip');
	      }, 3000);
	}
}
window.onclick = function(e){ //点击窗口,右键菜单隐藏
	var menu = document.getElementById("rightmenu-wrapper");
	menu.style.display = "none";
}

效果示例

参考资料

  • https://yywen.top/
  • https://www.zywvvd.com/notes/coding/web/front-end/html-rightclick-replace/html-rightclick-replace/

0 人点赞