JavaScript实现右键菜单

news2024/9/19 10:37:41

1、代码实现

window.onload = function () {
  (function () {
    // 自定义右键菜单内容并插入到body最后一个节点前
    let dom = `
      <div id="rightMenuBars">
          <div class="rightMenu-group rightMenu-small">
              <div class="rightMenu-item">
                  <i class="fa fa-chevron-left" aria-hidden="true"></i>
              </div>
              <div class="rightMenu-item">
                  <i class="fa fa-chevron-right" aria-hidden="true"></i>
              </div>
              <div class="rightMenu-item">
                  <i class="fa fa-refresh" aria-hidden="true"></i>
              </div>
              <div class="rightMenu-item">
                  <i class="fa fa-chevron-up" aria-hidden="true"></i>
              </div>
          </div>
      </div>
      <div id="rightMenuLinks">
          <div class="rightMenu-group rightMenu-line">
              <a class="rightMenu-item">
                  <i class="fa fa-photo" aria-hidden="true"></i>
                  <span>蓝猫图床</span>
              </a>
              <a class="rightMenu-item">
                  <i class="fa fa-cloud" aria-hidden="true"></i>
                  <span>个人云盘</span>
              </a>
              <a class="rightMenu-item">
                  <i class="fa fa-book" aria-hidden="true"></i>
                  <span>书籍阅读</span>
              </a>
              <a class="rightMenu-item">
                  <i class="fa fa-external-link" aria-hidden="true"></i>
                  <span>接口文档</span>
              </a>
          </div>
      </div>
      `;
    let rightMenuDiv = document.createElement("div");
    rightMenuDiv.id = "rightMenu";
    let body = document.body;
    rightMenuDiv.innerHTML = dom;
    body.insertBefore(rightMenuDiv, body.lastChild);

    // 引入外部css文件
    let link = document.createElement("link");
    link.rel = "stylesheet";
    link.type = "text/css";
    link.href =
      "https://static.likepoems.com/cdn/common/botui/releases/v4.7.0/css/font-awesome.min.css";
    document.head.appendChild(link);

    /* 创建style标签并设置菜单样式 */
    let rightMenuStyle = document.createElement("style");
    rightMenuStyle.innerHTML =
      "#rightMenu{display:none;font-size:20px;position:fixed;padding:0 0.25rem;width:9rem;height:fit-content;top:10%;left:10%;background-color: rgb(calc(0 + 255 * 0.92), calc(150 + (255 - 150) * 0.92), calc(136 + (255 - 136) * 0.92));;-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);transform:translateZ(0);color:#32325d;border-radius:12px;z-index:999;border:1px solid #e3e8f7;user-select:none;box-shadow:0 0 12px 4px rgba(0,0,0,0.05);transition:border 0.3s;font-weight:500;}#rightMenu:hover{border:1px solid #009688;box-shadow:0 8px 12px -3px #4259ef23;}#rightMenu .rightMenu-group{padding:0.35rem 0.3rem;transition:0.3s;}#rightMenu .rightMenu-line{border-top:1px dashed #4259ef23;}#rightMenu .rightMenu-group.rightMenu-small{display:flex;justify-content:space-between;}#rightMenu .rightMenu-group .rightMenu-item{border-radius:8px;transition:0.3s;}#rightMenu .rightMenu-line .rightMenu-item{margin:0.25rem 0;padding:0.25rem 0;}#rightMenu .rightMenu-group a{background-color:transparent;color:#32325d;text-decoration:none;transition:all 0.2s ease 0s;overflow-wrap:break-word;-webkit-user-drag:none;}#rightMenu .rightMenu-group.rightMenu-line .rightMenu-item{display:flex;}#rightMenu .rightMenu-group .rightMenu-item:hover{cursor: pointer !important;background-color:#009688;color:#fff;box-shadow:0 8px 12px -3px #4259ef23;}#rightMenu .rightMenu-group .rightMenu-item i{display:inline-block;text-align:center;line-height:1.5rem;width:1.5rem;padding:0 0.25rem;font-size:18px;color:#32325d;}#rightMenu .rightMenu-line .rightMenu-item i{margin:0 0.25rem;}#rightMenu .rightMenu-group .rightMenu-item span{line-height:1.5rem;}.rightMenu-small .rightMenu-item{width:30px;height:30px;line-height:30px;display:flex;align-items:center;justify-content:center;}";
    document.getElementsByTagName("head").item(0).appendChild(rightMenuStyle);
  })();

  // 如果菜单已经存在
  let rightMenu = document.getElementById("rightMenu");
  if (rightMenu) {
    // 定义菜单显示与隐藏的方法
    let rm = {};
    rm.showRightMenu = function (e, t = 0, l = 0) {
      let o = rightMenu;
      o.style.cssText = `top: ${t}px; left: ${l}px`;
      e ? (o.style.display = "block") : (o.style.display = "none");
    };
    rm.hideRightMenu = function () {
      rm.showRightMenu(!1);
    };
    let rmWidth = parseInt(rightMenu.style.width);
    let rmHeight = parseInt(rightMenu.style.height);

    // 定义键盘事件(主要用于屏蔽鼠标右键以及禁止打开开发者工具)
    document.onkeydown = () => {
      let e = window.event || arguments[0];
      //屏蔽F12
      if (e.keyCode == 123) {
        return false;
        //屏蔽Ctrl+Shift+I
      } else if (e.ctrlKey && e.shiftKey && e.keyCode == 73) {
        return false;
        //屏蔽Shift+F10
      } else if (e.shiftKey && e.keyCode == 121) {
        return false;
      }
    };

    // 鼠标右键按下的事件
    window.oncontextmenu = function (e) {
      // 阻止默认行为
      e.preventDefault();
      e = e || window.event;
      // 当可视宽度 > 768时显示菜单
      if (document.body.clientWidth > 768) {
        let t = e.clientY;
        let l = e.clientX + 10;
        return (
          (rmWidth = rmWidth || 155),
          (rmHeight = rmHeight || 255),
          l + rmWidth > window.innerWidth && (l -= rmWidth + 10),
          t + rmHeight > window.innerHeight &&
            (t -= t + rmHeight - window.innerHeight),
          rm.showRightMenu(!0, t, l),
          !1
        );
      }
    };

    // 鼠标按下事件(点击除去菜单的其它区域)
    document.addEventListener("click", (e) => {
      // 如果当前元素或祖先元素中存在rightMenu,则隐藏
      if (!e.target.closest("#rightMenu")) {
        rightMenu.style.display = "none";
      }
    });

    // 点击菜单操作栏图标的事件
    document.getElementById("rightMenuBars").addEventListener("click", (e) => {
      const inner = e.target?.className;
      switch (inner) {
        case "fa fa-chevron-left":
          // 向后
          history.back();
          break;
        case "fa fa-chevron-right":
          // 向前
          history.forward();
          break;
        case "fa fa-refresh":
          // 刷新
          window.location.reload();
          break;
        case "fa fa-chevron-up":
          // 回到顶部
          // 获取点击时的scrollTop值
          let scrollTop = document.documentElement.scrollTop - 0;
          let t = setInterval(function () {
            // 缓动动画,每次走剩余距离的一半
            scrollTop = scrollTop / 2;
            // 定义临界值
            if (scrollTop <= 5) {
              clearInterval(t);
              scrollTop = 0;
            }
            document.documentElement.scrollTop = scrollTop + 0;
          }, 16.666);
          break;
      }
      rm.hideRightMenu();
    });

    // 点击菜单显示栏文字事件
    document.getElementById("rightMenuLinks").addEventListener("click", (e) => {
      const tag = e.target?.tagName?.toLowerCase();
      const inner = e.target?.innerText;
      if (tag === "a" || tag === "span" || tag === "i") {
        rm.hideRightMenu();
      }
      switch (inner) {
        case "蓝猫图床":
          window.open("https://bluecat.likepoems.com");
          break;
        case "个人云盘":
          window.open("https://pan.likepoems.com");
          break;
        case "接口文档":
          window.open("https://api.likepoems.com/");
          break;
        case "书籍阅读":
          window.open("https://reader.likepoems.com/");
          break;
      }
    });
  }
};

2、效果演示

博客右键菜单js实现"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1238764.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C#开发的OpenRA游戏之属性RenderSprites(8)

C#开发的OpenRA游戏之属性RenderSprites(8) 本文开始学习RenderSprites属性,这个属性是跟渲染有关的,因此它就摄及颜色相关的内容,所以我们先来学习一下调色板,这是旧游戏的图片文件保存的格式,如果放在现代来看,不会再采用这种方法,毕竟现在存储空间变大,便宜了,并…

RubbleDB: CPU-Efficient Replication with NVMe-oF

RubbleDB: CPU-Efficient Replication with NVMe-oF 前言 这是ATC2023的文章&#xff0c;作者来自哥伦比亚大学这篇工作在LSM-tree多副本存储的场景下&#xff0c;利用NVMe-oF技术避免了LSM-tree副本上的重复合并&#xff0c;减少了CPU开销。 Introduction 为了提供高可用性…

练习九-利用状态机实现比较复杂的接口设计

练习九-利用状态机实现比较复杂的接口设计 1&#xff0c;任务目的&#xff1a;2&#xff0c;RTL代码3&#xff0c;RTL原理框图4&#xff0c;测试代码5&#xff0c;波形输出 1&#xff0c;任务目的&#xff1a; &#xff08;1&#xff09;学习运用状态机控制的逻辑开关&#xff…

vue history路径编码

记录今天遇到的一个问题&#xff1a; 问题现状 有一个需要前端伪造302进行重定向的需求&#xff0c;我们需要将这样的一个路径&#xff1a;http://xxx.com/system-name/#/index&#xff0c;拼接在跳转地址的后面&#xff0c;进行重定向。拼接的方式是这样的&#xff1a; htt…

暗物质探测器认知教学VR元宇宙平台打破传统束缚

“飞船正在上升&#xff0c;马上就冲出大气层了!”这是一位在1&#xff1a;1还原的神舟飞船返回舱内借助VR设备置身元宇宙世界&#xff0c;沉浸式体验升空全过程的游客兴奋地说道。不仅如此&#xff0c;在载人飞船训练期&#xff0c;元宇宙技术为航天员虚拟一个逼真的太空世界&…

口碑好的猫罐头有哪些?宠物店受欢迎的5款猫罐头推荐!

快到双十二啦&#xff01;铲屎官们是时候给家里猫主子囤猫罐头了。许多铲屎官看大促的各种品牌宣传&#xff0c;看到眼花缭乱&#xff0c;不知道选哪些猫罐头好&#xff0c;胡乱选又怕踩坑。 口碑好的猫罐头有哪些&#xff1f;作为一个经营宠物店7年的老板&#xff0c;活动期间…

Windows平台如何实现RTSP流二次编码并添加动态水印后推送RTMP或轻量级RTSP服务

技术背景 我们在对接RTSP播放器相关的技术诉求的时候&#xff0c;遇到这样的需求&#xff0c;客户做特种设备巡检的&#xff0c;需要把摄像头拍到的RTSP流拉下来&#xff0c;然后添加动态水印后&#xff0c;再生成新的RTSP URL&#xff0c;供平台调用。真个流程需要延迟尽可能…

LL(1)语法分析程序设计与实现

制作一个简单的C语言词法分析程序_用c语言编写词法分析程序-CSDN博客文章浏览阅读322次。C语言的程序中&#xff0c;有很单词多符号和保留字。一些单词符号还有对应的左线性文法。所以我们需要先做出一个单词字符表&#xff0c;给出对应的识别码&#xff0c;然后跟据对应的表格…

FlinkCDC实现主数据与各业务系统数据的一致性(瀚高、TIDB)

文章末尾附有flinkcdc对应瀚高数据库flink-cdc-connector代码下载地址 1、业务需求 目前项目有主数据系统和N个业务系统,为保障“一数一源”,各业务系统表涉及到主数据系统的字段都需用主数据系统表中的字段进行实时覆盖,这里以某个业务系统的一张表举例说明:业务系统表Ta…

社群乱象,社群玩法正解

社群乱象&#xff0c;社群玩法正解 越来越不喜欢混社群了&#xff0c;从原有的好几百社群&#xff0c;精简到剩两三个。就这两三个&#xff0c;也貌似奄奄一息&#xff0c;命不久矣的感觉。 现在的社群&#xff0c;妥妥的已经被各路妖魔鬼怪给玩坏了。童话觉得这里面还有不少…

vue3 iconify 图标几种使用 并加载本地 svg 图标

iconify iconify 与 iconify/vue 使用 下载 pnpm add iconify/vue -D使用 import { Icon } from "iconify/vue";<template><Icon icon"mdi-light:home" style"color: red; font-size: 43px" /><Icon icon"mdi:home-flo…

Spring Boot 邮件发送(五种类型的邮件)

邮件协议&#xff1a; SMTP、POP3、IMAP SMTP 协议全称为 Simple Mail Transfer Protocol&#xff0c;译作简单邮件传输协议&#xff0c;它定义了邮件客户端软件与 SMTP 服务器之间&#xff0c;以及 SMTP 服务器与 SMTP 服务器之间的通信规则。 用户先将邮件投递到腾讯的 SMT…

.nvmrc 文件使用详解

文章目录 1. 前言2. .nvmrc 是什么3. 创建 .nvmrc 文件4. 使用 .nvmrc 文件5. 终端自动切换版本 1. 前言 当开发多个项目时&#xff0c;每个项目运行环境要求的 node 版本不一样&#xff0c;那么我们就需要给每个项目指定 node 版本&#xff0c;也就是通过终端执行 nvm install…

虚拟摇杆OnJoystickMove未被调用,角色不移动

更改interaction type 为 event notification

Windows权限维持方法论

Windows权限维持方法论 1.注册表自启动2.组策略设置脚本启动3.计划任务4.服务自启动5.dll劫持6.直接上远程控制木马 1.注册表自启动 通过修改注册表自启动键值&#xff0c;添加一个木马程序路径&#xff0c;实现开机自启动 常用的注册表启动键&#xff1a; # Run键 HKEY_CU…

数据结构-栈的实现

1.栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。 压栈&…

2023年中国语言大模型行业发展趋势分析:预计未来行业将迎来高速增长[图]

自然语言处理&#xff08;NLP&#xff09;大模型是一种利用深度学习技术来理解、解释和生成人类语言的高参数模型。语言大模型通过编码解码的方式模仿人类处理语言的过程从而达到进行自然语言文本输出的能力。 语言大模型主要组成部分 资料来源&#xff1a;共研产业咨询&#…

【grep】从html表格中快速定位某个数据

文章目录 1 背景2 参考知识2.1 grep2.2 HTML基础语言标签 3 解决方案 1 背景 在html中是一堆表格、图片、文字什么的&#xff0c;想从表格中提取关键词为“GJC”后对应的数字&#xff0c;怎么办呢&#xff1f; 逐个打开html文件&#xff0c;“ctrlF”搜一下&#xff0c;然后复…

数字化文旅系统,让景区营销变得更加简单!

随着互联网的普及和信息技术的不断发展&#xff0c;越来越多的消费者开始通过互联网来获取旅游信息、预订旅游产品和服务。因此&#xff0c;文旅行业需要紧跟时代步伐&#xff0c;借助数字化技术来提高服务质量和效率&#xff0c;满足消费者对于便捷、个性化的需求。 1. 强大功…

每日OJ题_算法_双指针_力扣202. 快乐数

力扣202. 快乐数 202. 快乐数 - 力扣&#xff08;LeetCode&#xff09; 难度 简单 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为…