天天一個小技巧:實現自定義右鍵菜單(Context Menu)

logo

鼠標右擊網頁會彈出默認的瀏覽器菜單,可是不少時候咱們須要自定義右鍵菜單(好比:在線文檔編輯器、定製視頻播放器等)。今天咱們就來快速實現一個自定義右鍵菜單。git

預覽:github

demo

contextmenu 事件監聽

首先,咱們須要禁用瀏覽器彈出默認菜單的行爲,經過阻止 contextMenu 事件的默認行爲,並同時觸發自定義菜單的顯示:瀏覽器

document.addEventListener("contextmenu", (e) => {
  e.preventDefault();
  showMenu(e);
});

構造菜單

1. 實現單例

一個頁面中菜單應該只有一個實例,因此咱們運用單例模式去建立菜單,典型的單例構造器能夠實現爲:app

const ContextMenu = function (options) {
  // 惟一實例
  let instance;

  // 建立實例方法
  function createMenu() {
    // todo
  }

  return {
    // 獲取實例的惟一方式
    getInstance: function () {
      if (!instance) {
        instance = createMenu();
      }
      return instance;
    },
  };
};

2. 建立菜單實例

即實現上面的 createMenu 方法。編輯器

菜單的具體配置經過 options 傳入,options 的結構定義爲:ide

options: {
  menus: [{
    name: string, // 菜單名稱
    onClick: Function // 菜單點擊回調
  }]
 }

經過遍歷 options.menus 生成菜單列表,並掛載到 body 中,並最終返回菜單的實例:spa

function createMenu() {
  const ul = document.createElement("ul");
  ul.classList.add("custom-context-menu");
  const { menus } = options;
  if (menus && menus.length > 0) {
    for (let menu of menus) {
      const li = document.createElement("li");
      li.textContent = menu.name;
      li.onclick = menu.onClick;
      ul.appendChild(li);
    }
  }
  const body = document.querySelector("body");
  body.appendChild(ul);
  return ul;
}

建立菜單的主要邏輯就完成了。code

3. 初始化菜單

接下來向 ContextMenu 中傳入 options 以初始化單例構造器:視頻

const menuSinglton = ContextMenu({
  menus: [
    {
      name: "custom menu 1",
      onClick: function (e) {
        console.log("menu1 clicked");
      },
    },
    {
      name: "custom menu 2",
      onClick: function (e) {
        console.log("menu2 clicked");
      },
    },
    {
      name: "custom menu 3",
      onClick: function (e) {
        console.log("menu3 clicked");
      },
    },
  ],
});

初始化完成後,即可以經過 menuSinglton.getInstance() 獲取菜單實例了。blog

顯示菜單

當咱們右擊頁面時,獲取到鼠標的座標,設置菜單爲固定定位(position: fixed),並將其左上角位置設置爲鼠標座標,以實現菜單在鼠標點擊位置的彈出:

function showMenu(e) {
  const menus = menuSinglton.getInstance();
  menus.style.top = `${e.clientY}px`;
  menus.style.left = `${e.clientX}px`;
  menus.style.display = "block";
}

隱藏菜單

最後,當咱們點擊頁面中的其餘區域時須要將菜單隱藏:

function hideMenu(e) {
  const menus = menuSinglton.getInstance();
  menus.style.display = "none";
}

document.addEventListener("click", hideMenu);

大功告成!!

本文Demo參考:Codepen Trick by Day (2020-07-05) Custom Context Menus

天天一個小技巧,量變引發質變,但願你和我一塊兒天天多學一點,讓技術有趣一點。

全部示例將會彙總到個人 tricks-by-day github項目中,歡迎你們蒞臨指導 😊

相關文章
相關標籤/搜索