成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

前端實現右鍵自定義菜單

開發 前端
實現自定義菜單的邏輯并不復雜,也就是修改 contextmenu 事件的行為,顯示或隱藏自己寫的 div。

大家好,我是前端西瓜哥。

本文將講解 Web 頁面如何實現自定義菜單功能。

線上 demo:

https://codepen.io/F-star/pen/WNOvQVQ。

思路

核心思路是:注冊 contextmenu 事件,取消該事件的默認行為,然后通過 event 對象拿到光標相對視口的坐標位置(event.clientX 和 event.clientY),通過絕對定位的方式,將自己自定義的初始化時不可見的 div 塊顯示出來。

實現

DOM 結構

首先是 DOM 結構。結構依次為:

  • div.page-view 為注冊 contextmenu 事件的元素。
  • div.contextmenu-mask 是遮罩層,遮住整個窗口。它隨右鍵菜單出現而出現,作用是防止用戶調出右鍵菜單后,還可以點擊菜單外的按鈕。此外還可以添加有透明度的背景色,但這樣效果就類似彈窗了。一般來說,都是不設置底色的。
  • div.contextmenu-content 右鍵菜單的內容。
<div class="page-view">
點擊區域
</div>
<div class="contextmenu-mask" style="display: none;"></div>
<div class="contextmenu-content">
<div class="list">
<div class="item">復制</div>
<div class="item">剪切</div>
<div class="item">粘貼粘貼粘貼粘貼粘貼粘貼粘貼粘貼</div>
<div class="item">全選</div>
</div>
</div>

CSS 樣式

.page-view {
margin: 0 auto;
width: 90%;
height: calc(100vh - 30px);
background-color: azure;
}
/* 遮罩層 */
.contextmenu-mask {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
/* background-color: #000; */
/* opacity: .2; */
z-index: 45;
}
/* 菜單內容的容器 */
.contextmenu-content {
position: fixed;
left: 999999px;
top: 999999px;
z-index: 50;
user-select: none;
}
/* 例子使用內容 */
.list {
border: 1px solid #555;
border-radius: 4px;
min-width: 180px;
overflow: hidden; /* 處理圓角 */
}
.item {
box-sizing: border-box;
padding: 0 5px;
height: 30px;
line-height: 30px;
word-break: keep-all; /* 很重要,否則會換行 */
background-color: #fff;
cursor: default;
}
.item:hover {
background-color: dodgerblue;
color: #fff;
}

這里有幾個注意點:

  • contextmenu-content 并沒有使用 display: none 的方式進行隱藏,而是通過設置非常大的 left 和 top 的方式跑到窗口外的遠方。這是有原因的,我們將會在后面的腳本邏輯中進行詳細講解。
  • item 需要設置 word-break: keep-all; 。因為當菜單跑到窗口外時,寬度會變成最小寬度,在這里是 180px。只有設置了該屬性和值,才能讓文字不換行,得到我們想要的寬度。
  • contextmenu-content 需要使用固定定位,不能使用絕對定位。因為設置了大值的 left 和 top 的元素,對不是 overflow: hidden 的容器元素,會產生一個非常長的滾動條。固定定位則不會。

腳本邏輯

右鍵顯示菜單

首先取消掉點擊區域的菜單事件的默認行為。

拿到光標的坐標,為防止菜單部分跑到窗口外,導致被切割,需要對坐標進行調整。對此我們需要再拿到 菜單的寬高、窗口可視區域寬高。

此外為了防止菜單邊緣緊貼窗口邊緣,效果不美觀,需要設置一個 最小 padding 值 參與計算。

被截斷的菜單:

緊貼窗口邊緣的菜單:

以設置橫坐標為例,有:

if (e.clientX + contextmenuWidth > document.documentElement.clientWidth - PADDING_RIGHT) {
finalX = e.clientX - contextmenuWidth
}

這里代碼的意思是:當預測發現當前光標作為菜單的左側時,會導致菜單右側一部分被切割,就以當前坐標作為菜單的右側,此時的左上角的坐標為光標減去菜單寬度的值。

完整代碼為:

const areaEl = document.querySelector('.page-view')
const mask = document.querySelector('.contextmenu-mask')
const contentEl = document.querySelector('.contextmenu-content')
/**
*
* @param {number} x 將要設置的菜單的左上角坐標 x
* @param {number} y 左上角 y
* @param {number} w 菜單的寬度
* @param {number} h 菜單的高度
* @returns {x, y} 調整后的坐標
*/
const adjustPos = (x, y, w, h) => {
const PADDING_RIGHT = 6 // 右邊留點空位,防止直接貼邊了,不好看
const PADDING_BOTTOM = 6 // 底部也留點空位
const vw = document.documentElement.clientWidth
const vh = document.documentElement.clientHeight
if (x + w > vw - PADDING_RIGHT) x -= w
if (y + h > vh - PADDING_BOTTOM) y -= h
return {x, y}
}
const onContextMenu = e => {
e.preventDefault()
const rect = contentEl.getBoundingClientRect()
// console.log(rect)
const { x, y } = adjustPos(e.clientX, e.clientY, rect.width, rect.height)
showContextMenu(x, y)
}
// 阻止指定元素下的菜單事件
areaEl.addEventListener('contextmenu', onContextMenu, false)

隱藏右鍵菜單沒有使用常規的 display: none;,而是改為使用設置了很大值的 left 和 top。這是因為我要實現的是 自適應寬高 的右鍵菜單。

為此需要動態拿到菜單的寬高,需要用到

Element.getBoundingClientRect() 方法,而這個方法需要元素在 DOM 樹中,且為可見元素,才能拿到寬高,否則只能拿到兩個 0。

如果你要實現的菜單是手動寫死寬度的,高度通過菜單項的數量來計算的,那么隱藏菜單最好的方案是 display: none。

隱藏菜單和點擊菜單項

然后就是點擊遮罩層,隱藏菜單和遮罩。以及點擊菜單項,執行對應的命令

const hideContextMenu = () => {
mask.style.display = 'none'
contentEl.style.top = '99999px'
contentEl.style.left = '99999px'
}
// 點擊蒙版,隱藏
mask.addEventListener('mousedown', () => {
hideContextMenu()
}, false)
// 點擊菜單,隱藏
contentEl.addEventListener('click', (e) => {
console.log('點擊:', e.target.textContent)
// 執行菜單項對應命令
hideContextMenu()
}, false)

其他要考慮的地方

  • 窗口縮小的情況:窗口縮小會導致右下方的菜單跑到窗口區域外,是否考慮監聽窗口事件。
  • 菜單上再點右鍵的邏輯:是以這個位置重新定位右鍵菜單,還是等同于點擊了左鍵的效果,還是不進行處理,彈出瀏覽器原生右鍵菜單,需要根據需求進行選擇。

結尾

實現自定義菜單的邏輯并不復雜,也就是修改 contextmenu 事件的行為,顯示或隱藏自己寫的 div。

但里面有些細節需要處理好,才能寫出一個沒有 bug 的優秀右鍵菜單。

責任編輯:姜華 來源: 今日頭條
相關推薦

2015-02-12 15:33:43

微信SDK

2015-02-12 15:38:26

微信SDK

2011-04-25 14:26:32

Ubuntu菜單

2011-09-05 18:54:03

windowsUbuntu

2009-12-24 10:04:31

WPF右鍵菜單

2009-09-07 22:00:15

LINQ自定義

2021-11-24 10:02:53

鴻蒙HarmonyOS應用

2013-11-13 00:51:22

微信微信公號微信公眾賬號

2011-12-06 09:48:24

Win7

2009-06-17 16:00:03

Hibernate自定

2009-09-03 13:34:03

.NET自定義控件

2013-01-09 17:22:38

Android開發Camera

2022-03-01 16:09:06

OpenHarmon鴻蒙單選組件

2015-07-29 10:31:16

Java緩存算法

2022-12-07 08:56:27

SpringMVC核心組件

2022-04-01 15:59:22

SQLPostgreSQL審計

2023-01-03 07:40:27

自定義滑塊組件

2023-10-24 13:48:50

自定義注解舉值驗證

2011-04-21 15:22:27

ArcGIS Engi

2014-09-24 11:45:15

微信企業號開發
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品久久久久久久久久久久午夜片 | 偷偷操视频 | 一区免费 | 国产一区在线视频 | 精品国产不卡一区二区三区 | 日本五月婷婷 | 在线一区视频 | 成人在线视频观看 | 国产99久久精品一区二区永久免费 | 欧美一卡二卡在线 | 国产精品完整版 | 99re在线视频观看 | v片网站 | 中文字幕欧美一区二区 | 日中文字幕在线 | 人操人免费视频 | 九九爱这里只有精品 | 精品国产伦一区二区三区观看方式 | 欧美激情精品久久久久久变态 | 成人在线视频免费观看 | 亚洲国产成人久久综合一区,久久久国产99 | 色综合99| 在线播放国产一区二区三区 | 久久久久综合 | 91av在线免费观看 | 成人不卡| 国产亚洲精品美女久久久久久久久久 | 久久精品国产99国产精品亚洲 | 成人av免费播放 | 亚洲欧美日韩系列 | 国产一级一级国产 | 亚洲综合色 | 精品国产一级 | 欧美a级成人淫片免费看 | 日韩视频在线一区二区 | 男人av在线| 最新av在线播放 | 神马九九 | 国产一区二区三区免费 | 国产一区999 | 日日天天 |